diff --git a/build/modules.conf.in b/build/modules.conf.in index a6c32f3960..d33982a584 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -25,6 +25,7 @@ applications/mod_fsv #applications/mod_memcache #applications/mod_spy applications/mod_cluechoo +applications/mod_valet_parking codecs/mod_g723_1 codecs/mod_amr #codecs/mod_amrwb diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml index 50208b78da..7cb7783046 100644 --- a/conf/autoload_configs/modules.conf.xml +++ b/conf/autoload_configs/modules.conf.xml @@ -51,6 +51,7 @@ + diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index e1390e7503..e14e8db0ad 100644 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -87,12 +87,10 @@ SWITCH_STANDARD_DIALPLAN(inline_dialplan_hunt) #define DETECT_SPEECH_SYNTAX " [] OR grammar [] OR pause OR resume" SWITCH_STANDARD_APP(detect_speech_function) { - char *argv[4]; - int argc; + char *lbuf = NULL; - if (!switch_strlen_zero(data) && (lbuf = switch_core_session_strdup(session, data)) - && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { + if (!strcasecmp(argv[0], "grammar") && argc >= 1) { switch_ivr_detect_speech_load_grammar(session, argv[1], argv[2]); } else if (!strcasecmp(argv[0], "nogrammar")) { diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.2008.vcproj b/src/mod/applications/mod_valet_parking/mod_valet_parking.2008.vcproj new file mode 100644 index 0000000000..903860d5f3 --- /dev/null +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.2008.vcproj @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c new file mode 100644 index 0000000000..484cd6c2f3 --- /dev/null +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c @@ -0,0 +1,206 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2009, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * mod_valet_parking.c -- Valet Parking Module + * + */ +#include + +/* Prototypes */ +SWITCH_MODULE_LOAD_FUNCTION(mod_valet_parking_load); + +/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime) + * Defines a switch_loadable_module_function_table_t and a static const char[] modname + */ +SWITCH_MODULE_DEFINITION(mod_valet_parking, mod_valet_parking_load, NULL, NULL); + +typedef struct { + switch_hash_t *hash; + switch_mutex_t *mutex; + switch_memory_pool_t *pool; +} valet_lot_t; + +static valet_lot_t globals = { 0 }; + + +static valet_lot_t *valet_find_lot(const char *name) +{ + valet_lot_t *lot; + + if (!(lot = switch_core_hash_find(globals.hash, name))) { + switch_zmalloc(lot, sizeof(*lot)); + switch_mutex_init(&lot->mutex, SWITCH_MUTEX_NESTED, globals.pool); + switch_core_hash_init(&lot->hash, NULL); + switch_core_hash_insert(globals.hash, name, lot); + } + return lot; +} + +static switch_status_t valet_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) +{ + switch (itype) { + case SWITCH_INPUT_TYPE_DTMF: + { + switch_dtmf_t *dtmf = (switch_dtmf_t *) input; + + if (dtmf->digit == '#') { + return SWITCH_STATUS_BREAK; + } + } + default: + break; + } + + return SWITCH_STATUS_SUCCESS; +} + + +#define VALET_APP_SYNTAX " |[ask [] [] [] []]" +SWITCH_STANDARD_APP(valet_parking_function) +{ + char *argv[6], *lbuf; + int argc; + switch_channel_t *channel = switch_core_session_get_channel(session); + + if (!switch_strlen_zero(data) && (lbuf = switch_core_session_strdup(session, data)) + && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) { + char *lot_name = argv[0]; + char *ext = argv[1]; + valet_lot_t *lot; + char *uuid; + const char *music = "silence"; + const char *tmp = NULL; + switch_status_t status; + switch_input_args_t args = { 0 }; + char dbuf[10]; + + lot = valet_find_lot(lot_name); + switch_assert(lot); + + if (!strcasecmp(ext, "ask")) { + const char *prompt = "ivr/ivr-enter_ext_pound.wav"; + char dtmf_buf[12] = ""; + int min = 1; + int max = 11; + int to = 10000; + int i; + + tmp = argv[2] ? argv[2] : switch_channel_get_variable(channel, "valet_ext_min"); + if (tmp) { + if ((i = atoi(tmp)) > 0) { + min = i; + } + } + + tmp = argv[3] ? argv[3] : switch_channel_get_variable(channel, "valet_ext_max"); + if (tmp) { + if ((i = atoi(tmp)) > 0) { + max = i; + } + } + + tmp = argv[4] ? argv[4] : switch_channel_get_variable(channel, "valet_ext_to"); + if (tmp) { + if ((i = atoi(tmp)) > 0) { + to = i; + } + } + + tmp = argv[5] ? argv[5] : switch_channel_get_variable(channel, "valet_ext_prompt"); + if (tmp) { + prompt = tmp; + } + + do { + status = switch_ivr_read(session, min, max, prompt, NULL, dtmf_buf, sizeof(dtmf_buf), to, "#"); + } while (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_FALSE); + + if (status == SWITCH_STATUS_SUCCESS) { + ext = dtmf_buf; + } else { + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + } + } + + switch_mutex_lock(lot->mutex); + if ((uuid = switch_core_hash_find(lot->hash, ext))) { + switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), uuid); + switch_mutex_unlock(lot->mutex); + return; + } + + if (!(tmp = switch_channel_get_variable(channel, "valet_hold_music"))) { + tmp = switch_channel_get_variable(channel, "hold_music"); + } + if (tmp) music = tmp; + + switch_core_hash_insert(lot->hash, ext, switch_core_session_get_uuid(session)); + + args.input_callback = valet_on_dtmf; + args.buf = dbuf; + args.buflen = sizeof(dbuf); + + switch_mutex_unlock(lot->mutex); + if (!strcasecmp(music, "silence")) { + switch_ivr_collect_digits_callback(session, &args, 0, 0); + } else { + switch_ivr_play_file(session, NULL, music, &args); + } + switch_mutex_lock(lot->mutex); + switch_core_hash_delete(lot->hash, ext); + switch_mutex_unlock(lot->mutex); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", VALET_APP_SYNTAX); + } +} + +/* Macro expands to: switch_status_t mod_valet_parking_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */ +SWITCH_MODULE_LOAD_FUNCTION(mod_valet_parking_load) +{ + switch_application_interface_t *app_interface; + + switch_core_hash_init(&globals.hash, NULL); + globals.pool = pool; + + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + SWITCH_ADD_APP(app_interface, "valet_park", "valet_park", "valet_park", valet_parking_function, VALET_APP_SYNTAX, SAF_NONE); + + return SWITCH_STATUS_NOUNLOAD; +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4 + */