Index: funcs/func_devstate.c =================================================================== --- funcs/func_devstate.c (revision 105411) +++ funcs/func_devstate.c (working copy) @@ -24,14 +24,22 @@ * * \ingroup functions * - * \note Props go out to Ahrimanes in \#asterisk for requesting this at 4:30 AM + * \note Props go out to Ahrimanes in #asterisk for requesting this at 4:30 AM * when I couldn't sleep. :) */ +/* + * - Added the ability to set device state via CLI :) + * Paul was here Feb 28/08 + */ + + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") +#include + #include "asterisk/module.h" #include "asterisk/channel.h" #include "asterisk/pbx.h" @@ -40,86 +48,100 @@ #include "asterisk/devicestate.h" #include "asterisk/cli.h" #include "asterisk/astdb.h" -#include "asterisk/app.h" static const char astdb_family[] = "CustomDevstate"; -static int devstate_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) +static const char *ast_devstate_str(int state) { + const char *res = "UNKNOWN"; + + switch (state) { + case AST_DEVICE_UNKNOWN: + break; + case AST_DEVICE_NOT_INUSE: + res = "NOT_INUSE"; + break; + case AST_DEVICE_INUSE: + res = "INUSE"; + break; + case AST_DEVICE_BUSY: + res = "BUSY"; + break; + case AST_DEVICE_INVALID: + res = "INVALID"; + break; + case AST_DEVICE_UNAVAILABLE: + res = "UNAVAILABLE"; + break; + case AST_DEVICE_RINGING: + res = "RINGING"; + break; + case AST_DEVICE_RINGINUSE: + res = "RINGINUSE"; + break; + case AST_DEVICE_ONHOLD: + res = "ONHOLD"; + break; + } + + return res; +} + +static int ast_devstate_val(const char *val) +{ + if (!strcasecmp(val, "NOT_INUSE")) + return AST_DEVICE_NOT_INUSE; + else if (!strcasecmp(val, "INUSE")) + return AST_DEVICE_INUSE; + else if (!strcasecmp(val, "BUSY")) + return AST_DEVICE_BUSY; + else if (!strcasecmp(val, "INVALID")) + return AST_DEVICE_INVALID; + else if (!strcasecmp(val, "UNAVAILABLE")) + return AST_DEVICE_UNAVAILABLE; + else if (!strcasecmp(val, "RINGING")) + return AST_DEVICE_RINGING; + else if (!strcasecmp(val, "RINGINUSE")) + return AST_DEVICE_RINGINUSE; + else if (!strcasecmp(val, "ONHOLD")) + return AST_DEVICE_ONHOLD; + + return AST_DEVICE_UNKNOWN; +} + +static int devstate_read(struct ast_channel *chan, char *cmd, char *data, + char *buf, size_t len) +{ ast_copy_string(buf, ast_devstate_str(ast_device_state(data)), len); return 0; } -static int devstate_write(struct ast_channel *chan, const char *cmd, char *data, const char *value) +static int devstate_write(struct ast_channel *chan, char *function, + char *data, const char *value) { size_t len = strlen("Custom:"); if (strncasecmp(data, "Custom:", len)) { - ast_log(LOG_WARNING, "The DEVICE_STATE function can only be used to set 'Custom:' device state!\n"); + ast_log(LOG_WARNING, "The DEVSTATE function can only be used to set 'Custom:' device state!\n"); return -1; } data += len; if (ast_strlen_zero(data)) { - ast_log(LOG_WARNING, "DEVICE_STATE function called with no custom device name!\n"); + ast_log(LOG_WARNING, "DEVSTATE function called with no custom device name!\n"); return -1; } - ast_db_put(astdb_family, data, value); + ast_db_put(astdb_family, data, (char *) value); - ast_devstate_changed(ast_devstate_val(value), "Custom:%s", data); + ast_log(LOG_WARNING, "Changing %s to %s\n", data, value); + ast_device_state_changed("Custom:%s", data); return 0; } -enum { - HINT_OPT_NAME = (1 << 0), -}; - -AST_APP_OPTIONS(hint_options, BEGIN_OPTIONS - AST_APP_OPTION('n', HINT_OPT_NAME), -END_OPTIONS ); - -static int hint_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) +static int custom_devstate_callback(const char *data) { - char *exten, *context; - AST_DECLARE_APP_ARGS(args, - AST_APP_ARG(exten); - AST_APP_ARG(options); - ); - struct ast_flags opts = { 0, }; - int res; - - if (ast_strlen_zero(data)) { - ast_log(LOG_WARNING, "The HINT function requires an extension\n"); - return -1; - } - - AST_STANDARD_APP_ARGS(args, data); - - if (ast_strlen_zero(args.exten)) { - ast_log(LOG_WARNING, "The HINT function requires an extension\n"); - return -1; - } - - context = exten = args.exten; - strsep(&context, "@"); - if (ast_strlen_zero(context)) - context = "default"; - - if (!ast_strlen_zero(args.options)) - ast_app_parse_options(hint_options, &opts, NULL, args.options); - - if (ast_test_flag(&opts, HINT_OPT_NAME)) - res = ast_get_hint(NULL, 0, buf, len, chan, context, exten); - else - res = ast_get_hint(buf, len, NULL, 0, chan, context, exten); - - return !res; /* ast_get_hint returns non-zero on success */ -} - -static enum ast_device_state custom_devstate_callback(const char *data) -{ char buf[256] = ""; ast_db_get(astdb_family, data, buf, sizeof(buf)); @@ -127,70 +149,38 @@ return ast_devstate_val(buf); } -static char *handle_cli_funcdevstate_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) -{ - struct ast_db_entry *db_entry, *db_tree; +static int cli_funcdevstate_change(int fd, int argc, char *argv[]) { + size_t len = strlen("Custom:"); + ast_cli(fd, "Changing %s to %s\n", argv[2], argv[3]); - switch (cmd) { - case CLI_INIT: - e->command = "funcdevstate list"; - e->usage = - "Usage: funcdevstate list\n" - " List all custom device states that have been set by using\n" - " the DEVICE_STATE dialplan function.\n"; - return NULL; - case CLI_GENERATE: - return NULL; - } + if (strncasecmp(argv[2], "Custom:", len)) { + ast_log(LOG_WARNING, "The DEVSTATE function can only be used to set 'Custom:' device state!\n"); + return -1; + } + argv[2] += len; + if (ast_strlen_zero(argv[2])) { + ast_log(LOG_WARNING, "DEVSTATE function called with no custom device name!\n"); + return -1; + } - if (a->argc != e->args) - return CLI_SHOWUSAGE; + ast_db_put(astdb_family, argv[2], (char *) argv[3]); + + ast_log(LOG_WARNING, "Changing %s to %s\n", argv[2], argv[3]); + ast_device_state_changed("Custom:%s", argv[2]); - ast_cli(a->fd, "\n" - "---------------------------------------------------------------------\n" - "--- Custom Device States --------------------------------------------\n" - "---------------------------------------------------------------------\n" - "---\n"); + return 0; - db_entry = db_tree = ast_db_gettree(astdb_family, NULL); - for (; db_entry; db_entry = db_entry->next) { - const char *dev_name = strrchr(db_entry->key, '/') + 1; - if (dev_name <= (const char *) 1) - continue; - ast_cli(a->fd, "--- Name: 'Custom:%s' State: '%s'\n" - "---\n", dev_name, db_entry->data); - } - ast_db_freetree(db_tree); - db_tree = NULL; - ast_cli(a->fd, - "---------------------------------------------------------------------\n" - "---------------------------------------------------------------------\n" - "\n"); - - return CLI_SUCCESS; } -static char *handle_cli_devstate_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +static int cli_funcdevstate_list(int fd, int argc, char *argv[]) { struct ast_db_entry *db_entry, *db_tree; - switch (cmd) { - case CLI_INIT: - e->command = "devstate list"; - e->usage = - "Usage: devstate list\n" - " List all custom device states that have been set by using\n" - " the DEVICE_STATE dialplan function.\n"; - return NULL; - case CLI_GENERATE: - return NULL; - } + if (argc != 2) + return RESULT_SHOWUSAGE; - if (a->argc != e->args) - return CLI_SHOWUSAGE; - - ast_cli(a->fd, "\n" + ast_cli(fd, "\n" "---------------------------------------------------------------------\n" "--- Custom Device States --------------------------------------------\n" "---------------------------------------------------------------------\n" @@ -201,39 +191,42 @@ const char *dev_name = strrchr(db_entry->key, '/') + 1; if (dev_name <= (const char *) 1) continue; - ast_cli(a->fd, "--- Name: 'Custom:%s' State: '%s'\n" + ast_cli(fd, "--- name: 'custom:%s' state: '%s'\n" "---\n", dev_name, db_entry->data); } ast_db_freetree(db_tree); db_tree = NULL; - ast_cli(a->fd, + ast_cli(fd, "---------------------------------------------------------------------\n" "---------------------------------------------------------------------\n" "\n"); - return CLI_SUCCESS; + return RESULT_SUCCESS; } -static struct ast_cli_entry cli_funcdevstate_list_deprecated = AST_CLI_DEFINE(handle_cli_funcdevstate_list, "List currently known custom device states"); static struct ast_cli_entry cli_funcdevstate[] = { - AST_CLI_DEFINE(handle_cli_devstate_list, "List currently known custom device states", .deprecate_cmd = &cli_funcdevstate_list_deprecated), + { { "funcdevstate", "list", }, cli_funcdevstate_list, NULL, NULL }, + + { { "funcdevstate", "change", }, cli_funcdevstate_change, NULL, NULL }, + + }; static struct ast_custom_function devstate_function = { - .name = "DEVICE_STATE", + .name = "DEVSTATE", .synopsis = "Get or Set a device state", - .syntax = "DEVICE_STATE(device)", + .syntax = "DEVSTATE(device)", .desc = - " The DEVICE_STATE function can be used to retrieve the device state from any\n" + " The DEVSTATE function can be used to retrieve the device state from any\n" "device state provider. For example:\n" - " NoOp(SIP/mypeer has state ${DEVICE_STATE(SIP/mypeer)})\n" - " NoOp(Conference number 1234 has state ${DEVICE_STATE(MeetMe:1234)})\n" + " NoOp(SIP/mypeer has state ${DEVSTATE(SIP/mypeer)})\n" + " NoOp(Conference number 1234 has state ${DEVSTATE(MeetMe:1234)})\n" "\n" - " The DEVICE_STATE function can also be used to set custom device state from\n" + " The DEVSTATE function can also be used to set custom device state from\n" "the dialplan. The \"Custom:\" prefix must be used. For example:\n" - " Set(DEVICE_STATE(Custom:lamp1)=BUSY)\n" - " Set(DEVICE_STATE(Custom:lamp2)=NOT_INUSE)\n" + " Set(DEVSTATE(Custom:lamp1)=BUSY)\n" + " Set(DEVSTATE(Custom:lamp2)=NOT_INUSE)\n" "You can subscribe to the status of a custom device state using a hint in\n" "the dialplan:\n" " exten => 1234,hint,Custom:lamp1\n" @@ -245,28 +238,13 @@ .write = devstate_write, }; -static struct ast_custom_function hint_function = { - .name = "HINT", - .synopsis = "Get the devices set for a dialplan hint", - .syntax = "HINT(extension[@context][|options])", - .desc = - " The HINT function can be used to retrieve the list of devices that are\n" - "mapped to a dialplan hint. For example:\n" - " NoOp(Hint for Extension 1234 is ${HINT(1234)})\n" - "Options:\n" - " 'n' - Retrieve name on the hint instead of list of devices\n" - "", - .read = hint_read, -}; - static int unload_module(void) { int res = 0; res |= ast_custom_function_unregister(&devstate_function); - res |= ast_custom_function_unregister(&hint_function); - res |= ast_devstate_prov_del("Custom"); - res |= ast_cli_unregister_multiple(cli_funcdevstate, ARRAY_LEN(cli_funcdevstate)); + ast_devstate_prov_del("Custom"); + ast_cli_unregister_multiple(cli_funcdevstate, ARRAY_LEN(cli_funcdevstate)); return res; } @@ -274,25 +252,10 @@ static int load_module(void) { int res = 0; - struct ast_db_entry *db_entry, *db_tree; - /* Populate the device state cache on the system with all of the currently - * known custom device states. */ - db_entry = db_tree = ast_db_gettree(astdb_family, NULL); - for (; db_entry; db_entry = db_entry->next) { - const char *dev_name = strrchr(db_entry->key, '/') + 1; - if (dev_name <= (const char *) 1) - continue; - ast_devstate_changed(ast_devstate_val(db_entry->data), - "Custom:%s\n", dev_name); - } - ast_db_freetree(db_tree); - db_tree = NULL; - res |= ast_custom_function_register(&devstate_function); - res |= ast_custom_function_register(&hint_function); res |= ast_devstate_prov_add("Custom", custom_devstate_callback); - res |= ast_cli_register_multiple(cli_funcdevstate, ARRAY_LEN(cli_funcdevstate)); + ast_cli_register_multiple(cli_funcdevstate, ARRAY_LEN(cli_funcdevstate)); return res; }