diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/app_confbridge.c | 119 | ||||
-rw-r--r-- | apps/app_directed_pickup.c | 24 | ||||
-rw-r--r-- | apps/app_queue.c | 4 | ||||
-rw-r--r-- | apps/confbridge/conf_config_parser.c | 12 | ||||
-rw-r--r-- | apps/confbridge/include/confbridge.h | 1 |
5 files changed, 134 insertions, 26 deletions
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 7cede133e..177ee3717 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -106,6 +106,22 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") <para>exten => 1,n,ConfBridge(1)</para> </description> </function> + <function name="CONFBRIDGE_INFO" language="en_US"> + <synopsis> + Get information about a ConfBridge conference. + </synopsis> + <syntax> + <parameter name="type" required="true"> + <para>Type can be <literal>parties</literal>, <literal>admins</literal>, <literal>marked</literal>, or <literal>locked</literal>.</para> + </parameter> + <parameter name="conf" required="true"> + <para>Conf refers to the name of the conference being referenced.</para> + </parameter> + </syntax> + <description> + <para>This function returns a non-negative integer for valid conference identifiers (0 or 1 for <literal>locked</literal>) and "" for invalid conference identifiers.</para> + </description> + </function> <manager name="ConfbridgeList" language="en_US"> <synopsis> List participants in a conference. @@ -618,7 +634,8 @@ static void post_join_marked(struct conference_bridge *conference_bridge, struct if (other_conference_bridge_user == conference_bridge_user) { continue; } - if (ast_test_flag(&other_conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_conference_bridge_user->chan)) { + if (other_conference_bridge_user->playing_moh && !ast_bridge_suspend(conference_bridge->bridge, other_conference_bridge_user->chan)) { + other_conference_bridge_user->playing_moh = 0; ast_moh_stop(other_conference_bridge_user->chan); ast_bridge_unsuspend(conference_bridge->bridge, other_conference_bridge_user->chan); } @@ -664,6 +681,7 @@ static void post_join_marked(struct conference_bridge *conference_bridge, struct */ if (!conference_bridge->markedusers && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) { ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL); + conference_bridge_user->playing_moh = 1; } } } @@ -692,6 +710,7 @@ static void post_join_unmarked(struct conference_bridge *conference_bridge, stru */ if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) { ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL); + conference_bridge_user->playing_moh = 1; } return; } @@ -709,6 +728,7 @@ static void post_join_unmarked(struct conference_bridge *conference_bridge, stru /* Temporarily suspend the above participant from the bridge so we have control to stop MOH if needed */ if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) { + first_participant->playing_moh = 0; ast_moh_stop(first_participant->chan); ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan); } @@ -924,6 +944,7 @@ static void leave_conference_bridge(struct conference_bridge *conference_bridge, ast_bridge_remove(conference_bridge->bridge, other_participant->chan); } else if (ast_test_flag(&other_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_participant->chan)) { ast_moh_start(other_participant->chan, other_participant->u_profile.moh_class, NULL); + other_participant->playing_moh = 1; ast_bridge_unsuspend(conference_bridge->bridge, other_participant->chan); } } @@ -933,6 +954,7 @@ static void leave_conference_bridge(struct conference_bridge *conference_bridge, if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) { ast_moh_start(first_participant->chan, first_participant->u_profile.moh_class, NULL); + first_participant->playing_moh = 1; ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan); } } @@ -1192,14 +1214,22 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) { b_profile_name = args.b_profile_name; } - conf_find_bridge_profile(chan, b_profile_name, &conference_bridge_user.b_profile); + if (!conf_find_bridge_profile(chan, b_profile_name, &conference_bridge_user.b_profile)) { + ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name); + res = -1; + goto confbridge_cleanup; + } /* user profile name */ if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) { u_profile_name = args.u_profile_name; } - conf_find_user_profile(chan, u_profile_name, &conference_bridge_user.u_profile); + if (!conf_find_user_profile(chan, u_profile_name, &conference_bridge_user.u_profile)) { + ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name); + res = -1; + goto confbridge_cleanup; + } quiet = ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_QUIET); /* ask for a PIN immediately after finding user profile. This has to be @@ -1301,7 +1331,13 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) /* Play the Join sound to both the conference and the user entering. */ if (!quiet) { const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference_bridge_user.b_profile.sounds); + if (conference_bridge_user.playing_moh) { + ast_moh_stop(chan); + } ast_stream_and_wait(chan, join_sound, ""); + if (conference_bridge_user.playing_moh) { + ast_moh_start(chan, conference_bridge_user.u_profile.moh_class, NULL); + } ast_autoservice_start(chan); play_sound_file(conference_bridge, join_sound); ast_autoservice_stop(chan); @@ -1635,8 +1671,8 @@ int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel, /* See if music on hold is playing */ ao2_lock(conference_bridge); - if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) { - /* Just us so MOH is probably indeed going, let's stop it */ + if (conference_bridge_user->playing_moh) { + /* MOH is going, let's stop it */ ast_moh_stop(bridge_channel->chan); } ao2_unlock(conference_bridge); @@ -1646,7 +1682,7 @@ int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel, /* See if music on hold needs to be started back up again */ ao2_lock(conference_bridge); - if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) { + if (conference_bridge_user->playing_moh) { ast_moh_start(bridge_channel->chan, conference_bridge_user->u_profile.moh_class, NULL); } ao2_unlock(conference_bridge); @@ -2059,6 +2095,12 @@ static struct ast_custom_function confbridge_function = { .write = func_confbridge_helper, }; +static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len); +static struct ast_custom_function confbridge_info_function = { + .name = "CONFBRIDGE_INFO", + .read = func_confbridge_info, +}; + static int action_confbridgelist(struct mansession *s, const struct message *m) { const char *actionid = astman_get_header(m, "ActionID"); @@ -2370,7 +2412,68 @@ static int action_confbridgestoprecord(struct mansession *s, const struct messag return 0; } +static int func_confbridge_info(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) +{ + char *parse = NULL; + struct conference_bridge *bridge = NULL; + struct conference_bridge_user *participant = NULL; + struct conference_bridge tmp; + int count = 0; + AST_DECLARE_APP_ARGS(args, + AST_APP_ARG(type); + AST_APP_ARG(confno); + ); + /* parse all the required arguments and make sure they exist. */ + if (ast_strlen_zero(data)) { + return -1; + } + parse = ast_strdupa(data); + AST_STANDARD_APP_ARGS(args, parse); + if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) { + return -1; + } + if (!ao2_container_count(conference_bridges)) { + ast_log(LOG_ERROR, "No active conferneces.\n"); + return -1; + } + ast_copy_string(tmp.name, args.confno, sizeof(tmp.name)); + bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); + if (!bridge) { + ast_log(LOG_ERROR, "Confernece '%s' not found.\n", args.confno); + return -1; + } + + /* get the correct count for the type requested */ + ao2_lock(bridge); + if (!strncasecmp(args.type, "parties", 7)) { + AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { + count++; + } + } else if (!strncasecmp(args.type, "admins", 6)) { + AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { + if (ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) { + count++; + } + } + } else if (!strncasecmp(args.type, "marked", 6)) { + AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { + if (ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER)) { + count++; + } + } + } else if (!strncasecmp(args.type, "locked", 6)) { + count = bridge->locked; + } else { + ao2_unlock(bridge); + ao2_ref(bridge, -1); + return -1; + } + snprintf(buf, len, "%d", count); + ao2_unlock(bridge); + ao2_ref(bridge, -1); + return 0; +} /*! \brief Called when module is being unloaded */ static int unload_module(void) @@ -2378,6 +2481,7 @@ static int unload_module(void) int res = ast_unregister_application(app); ast_custom_function_unregister(&confbridge_function); + ast_custom_function_unregister(&confbridge_info_function); ast_cli_unregister_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry)); @@ -2409,6 +2513,9 @@ static int load_module(void) if ((ast_custom_function_register(&confbridge_function))) { return AST_MODULE_LOAD_FAILURE; } + if ((ast_custom_function_register(&confbridge_info_function))) { + return AST_MODULE_LOAD_FAILURE; + } if (!(record_tech.capabilities = ast_format_cap_alloc())) { return AST_MODULE_LOAD_FAILURE; } diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c index 38f24effc..63a7621ff 100644 --- a/apps/app_directed_pickup.c +++ b/apps/app_directed_pickup.c @@ -97,19 +97,6 @@ static const char app[] = "Pickup"; static const char app2[] = "PickupChan"; /*! \todo This application should return a result code, like PICKUPRESULT */ -/* Helper function that determines whether a channel is capable of being picked up */ -static int can_pickup(struct ast_channel *chan) -{ - if (!chan->pbx && !chan->masq && - !ast_test_flag(chan, AST_FLAG_ZOMBIE) && - (chan->_state == AST_STATE_RINGING || - chan->_state == AST_STATE_RING || - chan->_state == AST_STATE_DOWN)) { - return 1; - } - return 0; -} - struct pickup_by_name_args { const char *name; size_t len; @@ -121,7 +108,7 @@ static int pickup_by_name_cb(void *obj, void *arg, void *data, int flags) struct pickup_by_name_args *args = data; ast_channel_lock(target); - if (!strncasecmp(target->name, args->name, args->len) && can_pickup(target)) { + if (!strncasecmp(target->name, args->name, args->len) && ast_can_pickup(target)) { /* Return with the channel still locked on purpose */ return CMP_MATCH | CMP_STOP; } @@ -190,7 +177,7 @@ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const ch while ((target = ast_channel_iterator_next(iter))) { ast_channel_lock(target); - if ((chan != target) && can_pickup(target)) { + if ((chan != target) && ast_can_pickup(target)) { ast_log(LOG_NOTICE, "%s pickup by %s\n", target->name, chan->name); break; } @@ -217,7 +204,7 @@ static int find_by_mark(void *obj, void *arg, void *data, int flags) ast_channel_lock(target); tmp = pbx_builtin_getvar_helper(target, PICKUPMARK); - if (tmp && !strcasecmp(tmp, mark) && can_pickup(target)) { + if (tmp && !strcasecmp(tmp, mark) && ast_can_pickup(target)) { /* Return with the channel still locked on purpose */ return CMP_MATCH | CMP_STOP; } @@ -249,7 +236,8 @@ static int find_channel_by_group(void *obj, void *arg, void *data, int flags) struct ast_channel *chan = data;/*!< Channel wanting to pickup call */ ast_channel_lock(target); - if (chan != target && (chan->pickupgroup & target->callgroup) && can_pickup(target)) { + if (chan != target && (chan->pickupgroup & target->callgroup) + && ast_can_pickup(target)) { /* Return with the channel still locked on purpose */ return CMP_MATCH | CMP_STOP; } @@ -316,7 +304,7 @@ static int find_by_part(void *obj, void *arg, void *data, int flags) ast_channel_lock(target); if (len <= strlen(target->name) && !strncmp(target->name, part, len) - && can_pickup(target)) { + && ast_can_pickup(target)) { /* Return with the channel still locked on purpose */ return CMP_MATCH | CMP_STOP; } diff --git a/apps/app_queue.c b/apps/app_queue.c index 146cf63d6..be929c1dc 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -3482,7 +3482,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte if (o->stillgoing) { /* Keep track of important channels */ stillgoing = 1; if (o->chan) { - watchers[pos++] = o->chan; + if (pos < AST_MAX_WATCHERS) { + watchers[pos++] = o->chan; + } if (!start) start = o; else diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c index dbec32bba..3d1f31326 100644 --- a/apps/confbridge/conf_config_parser.c +++ b/apps/confbridge/conf_config_parser.c @@ -582,7 +582,7 @@ static int add_action_to_menu_entry(struct conf_menu_entry *menu_entry, enum con static int add_menu_entry(struct conf_menu *menu, const char *dtmf, const char *action_names) { - struct conf_menu_entry *menu_entry = NULL; + struct conf_menu_entry *menu_entry = NULL, *cur = NULL; int res = 0; char *tmp_action_names = ast_strdupa(action_names); char *action = NULL; @@ -691,6 +691,16 @@ static int add_menu_entry(struct conf_menu *menu, const char *dtmf, const char * return -1; } + /* remove any list entry with an identical DTMF sequence for overrides */ + AST_LIST_TRAVERSE_SAFE_BEGIN(&menu->entries, cur, entry) { + if (!strcasecmp(cur->dtmf, menu_entry->dtmf)) { + AST_LIST_REMOVE_CURRENT(entry); + ast_free(cur); + break; + } + } + AST_LIST_TRAVERSE_SAFE_END; + AST_LIST_INSERT_TAIL(&menu->entries, menu_entry, entry); return 0; diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h index 4b6c0615e..de467b5f7 100644 --- a/apps/confbridge/include/confbridge.h +++ b/apps/confbridge/include/confbridge.h @@ -215,6 +215,7 @@ struct conference_bridge_user { struct ast_bridge_features features; /*!< Bridge features structure */ struct ast_bridge_tech_optimizations tech_args; /*!< Bridge technology optimizations for talk detection */ unsigned int kicked:1; /*!< User has been kicked from the conference */ + unsigned int playing_moh:1; /*!< MOH is currently being played to the user */ AST_LIST_ENTRY(conference_bridge_user) list; /*!< Linked list information */ }; |