app_confbridge.c File Reference

Conference Bridge application. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include "asterisk/cli.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/bridge.h"
#include "asterisk/musiconhold.h"
#include "asterisk/say.h"
#include "asterisk/audiohook.h"
#include "asterisk/astobj2.h"
#include "confbridge/include/confbridge.h"
#include "asterisk/paths.h"
#include "asterisk/manager.h"
#include "asterisk/test.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/json.h"
#include "asterisk/format_cache.h"

Include dependency graph for app_confbridge.c:

Go to the source code of this file.

Defines

#define CONFERENCE_BRIDGE_BUCKETS   53
#define RECORD_FILENAME_INITIAL_SPACE   128

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int action_confbridgekick (struct mansession *s, const struct message *m)
static int action_confbridgelist (struct mansession *s, const struct message *m)
static void action_confbridgelist_item (struct mansession *s, const char *id_text, struct confbridge_conference *conference, struct confbridge_user *user, int waiting)
static int action_confbridgelistrooms (struct mansession *s, const struct message *m)
static int action_confbridgelock (struct mansession *s, const struct message *m)
static int action_confbridgemute (struct mansession *s, const struct message *m)
static int action_confbridgesetsinglevideosrc (struct mansession *s, const struct message *m)
static int action_confbridgestartrecord (struct mansession *s, const struct message *m)
static int action_confbridgestoprecord (struct mansession *s, const struct message *m)
static int action_confbridgeunlock (struct mansession *s, const struct message *m)
static int action_confbridgeunmute (struct mansession *s, const struct message *m)
static int action_dialplan_exec (struct ast_bridge_channel *bridge_channel, struct conf_menu_action *menu_action)
static int action_kick_last (struct confbridge_conference *conference, struct ast_bridge_channel *bridge_channel, struct confbridge_user *user)
static int action_lock_unlock_helper (struct mansession *s, const struct message *m, int lock)
static int action_mute_unmute_helper (struct mansession *s, const struct message *m, int mute)
static int action_playback (struct ast_bridge_channel *bridge_channel, const char *playback_file)
static int action_playback_and_continue (struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel, struct conf_menu *menu, const char *playback_file, const char *cur_dtmf, int *stop_prompts)
static int action_toggle_mute (struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel)
static int action_toggle_mute_participants (struct confbridge_conference *conference, struct confbridge_user *user)
static int alloc_playback_chan (struct confbridge_conference *conference)
static int announce_user_count (struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel)
 Announce number of users in the conference bridge to the caller.
static int cli_mute_unmute_helper (int mute, struct ast_cli_args *a)
static char * complete_confbridge_name (const char *line, const char *word, int pos, int state)
static char * complete_confbridge_participant (const char *conference_name, const char *line, const char *word, int pos, int state)
int conf_add_post_join_action (struct confbridge_user *user, int(*func)(struct confbridge_user *user))
 Queue a function to run with the given conference bridge user as an argument once the state transition is complete.
void conf_add_user_active (struct confbridge_conference *conference, struct confbridge_user *user)
 Add a conference bridge user as an unmarked active user of the conference.
void conf_add_user_marked (struct confbridge_conference *conference, struct confbridge_user *user)
 Add a conference bridge user as a marked active user of the conference.
void conf_add_user_waiting (struct confbridge_conference *conference, struct confbridge_user *user)
 Add a conference bridge user as an waiting user of the conference.
void conf_ended (struct confbridge_conference *conference)
 Callback to be called when the conference has become empty.
static int conf_get_pin (struct ast_channel *chan, struct confbridge_user *user)
const char * conf_get_sound (enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds)
 Looks to see if sound file is stored in bridge profile sounds, if not default sound is provided.
int conf_handle_dtmf (struct ast_bridge_channel *bridge_channel, struct confbridge_user *user, struct conf_menu_entry *menu_entry, struct conf_menu *menu)
 Once a DTMF sequence matches a sequence in the user's DTMF menu, this function will get called to perform the menu action.
void conf_handle_first_join (struct confbridge_conference *conference)
 Callback to execute any time we transition from zero to one active users.
int conf_handle_inactive_waitmarked (struct confbridge_user *user)
 Handle actions every time a waitmarked user joins w/o a marked user present.
int conf_handle_only_unmarked (struct confbridge_user *user)
 Handle actions whenever an unmarked user joins an inactive conference.
void conf_handle_second_active (struct confbridge_conference *conference)
 Handle when a conference moves to having more than one active participant.
static int conf_handle_talker_cb (struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking)
static int conf_is_recording (struct confbridge_conference *conference)
void conf_moh_start (struct confbridge_user *user)
 Start MOH for the conference user.
void conf_moh_stop (struct confbridge_user *user)
 Stop MOH for the conference user.
static void conf_moh_suspend (struct confbridge_user *user)
static void conf_moh_unsuspend (struct confbridge_user *user)
void conf_mute_only_active (struct confbridge_conference *conference)
 Attempt to mute/play MOH to the only user in the conference if they require it.
static int conf_rec_name (struct confbridge_user *user, const char *conf_name)
void conf_remove_user_active (struct confbridge_conference *conference, struct confbridge_user *user)
 Remove a conference bridge user from the unmarked active conference users in the conference.
void conf_remove_user_marked (struct confbridge_conference *conference, struct confbridge_user *user)
 Remove a conference bridge user from the marked active conference users in the conference.
void conf_remove_user_waiting (struct confbridge_conference *conference, struct confbridge_user *user)
 Remove a conference bridge user from the waiting conference users in the conference.
static int conf_start_record (struct confbridge_conference *conference)
static int conf_stop_record (struct confbridge_conference *conference)
void conf_update_user_mute (struct confbridge_user *user)
 Update the actual mute status of the user and set it on the bridge.
static int confbridge_exec (struct ast_channel *chan, const char *data)
 The ConfBridge application.
static int conference_bridge_cmp_cb (void *obj, void *arg, int flags)
 Comparison function used for conference bridges container.
static int conference_bridge_hash_cb (const void *obj, const int flags)
 Hashing function used for conference bridges container.
static void destroy_conference_bridge (void *obj)
 Destroy a conference bridge.
static int execute_menu_entry (struct confbridge_conference *conference, struct confbridge_user *user, struct ast_bridge_channel *bridge_channel, struct conf_menu_entry *menu_entry, struct conf_menu *menu)
static int func_confbridge_info (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int generic_lock_unlock_helper (int lock, const char *conference_name)
static int generic_mute_unmute_helper (int mute, const char *conference_name, const char *chan_name)
static void generic_mute_unmute_user (struct confbridge_conference *conference, struct confbridge_user *user, int mute)
static char * handle_cli_confbridge_kick (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_confbridge_list (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void handle_cli_confbridge_list_item (struct ast_cli_args *a, struct confbridge_user *user, int waiting)
static char * handle_cli_confbridge_lock (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_confbridge_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_confbridge_start_record (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_confbridge_stop_record (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_confbridge_unlock (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_confbridge_unmute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int handle_conf_user_join (struct confbridge_user *user)
 Call the proper join event handler for the user for the conference bridge's current state.
static int handle_conf_user_leave (struct confbridge_user *user)
 Call the proper leave event handler for the user for the conference bridge's current state.
static void handle_video_on_exit (struct confbridge_conference *conference, struct ast_channel *chan)
static void handle_video_on_join (struct confbridge_conference *conference, struct ast_channel *chan, int marked)
static int is_new_rec_file (const char *rec_file, struct ast_str **orig_rec_file)
static struct
confbridge_conference
join_conference_bridge (const char *conference_name, struct confbridge_user *user)
 Join a conference bridge.
static int kick_conference_participant (struct confbridge_conference *conference, const char *channel)
static void leave_conference (struct confbridge_user *user)
 Leave a conference.
static int load_module (void)
 Load the module.
static int play_file (struct ast_bridge_channel *bridge_channel, struct ast_channel *channel, const char *filename)
static int play_prompt_to_user (struct confbridge_user *user, const char *filename)
 Play back an audio file to a channel.
int play_sound_file (struct confbridge_conference *conference, const char *filename)
 Play sound file into conference bridge.
static int play_sound_helper (struct confbridge_conference *conference, const char *filename, int say_number)
static int play_sound_number (struct confbridge_conference *conference, int say_number)
 Play number into the conference bridge.
static int register_channel_tech (struct ast_channel_tech *tech)
static int reload (void)
static void send_conf_end_event (struct confbridge_conference *conference)
static void send_conf_start_event (struct confbridge_conference *conference)
static void send_conf_stasis (struct confbridge_conference *conference, struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *extras, int channel_topic)
static void send_join_event (struct confbridge_user *user, struct confbridge_conference *conference)
static void send_leave_event (struct confbridge_user *user, struct confbridge_conference *conference)
static void send_mute_event (struct confbridge_user *user, struct confbridge_conference *conference)
static void send_start_record_event (struct confbridge_conference *conference)
static void send_stop_record_event (struct confbridge_conference *conference)
static void send_unmute_event (struct confbridge_user *user, struct confbridge_conference *conference)
static void set_rec_filename (struct confbridge_conference *conference, struct ast_str **filename, int is_new)
static int sound_file_exists (const char *filename)
static int unload_module (void)
 Called when module is being unloaded.
static void unregister_channel_tech (struct ast_channel_tech *tech)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Conference Bridge Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, }
static const char app [] = "ConfBridge"
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_confbridge []
static struct ast_custom_function confbridge_function
static struct ast_custom_function confbridge_info_function
struct ao2_containerconference_bridges
 Container to hold all conference bridges in progress.


Detailed Description

Conference Bridge application.

Author:
Joshua Colp <jcolp@digium.com> 

David Vossel <dvossel@digium.com> 
This is a conference bridge application utilizing the bridging core.

Definition in file app_confbridge.c.


Define Documentation

#define CONFERENCE_BRIDGE_BUCKETS   53

Number of buckets our conference bridges container can have

Definition at line 328 of file app_confbridge.c.

Referenced by load_module().

#define RECORD_FILENAME_INITIAL_SPACE   128

Initial recording filename space.

Definition at line 331 of file app_confbridge.c.

Referenced by is_new_rec_file(), and join_conference_bridge().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 3434 of file app_confbridge.c.

static void __unreg_module ( void   )  [static]

Definition at line 3434 of file app_confbridge.c.

static int action_confbridgekick ( struct mansession s,
const struct message m 
) [static]

Definition at line 3019 of file app_confbridge.c.

References ao2_container_count(), ao2_find, ao2_ref, ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), kick_conference_participant(), and OBJ_KEY.

Referenced by load_module().

03020 {
03021    const char *conference_name = astman_get_header(m, "Conference");
03022    const char *channel = astman_get_header(m, "Channel");
03023    struct confbridge_conference *conference;
03024    int found;
03025 
03026    if (ast_strlen_zero(conference_name)) {
03027       astman_send_error(s, m, "No Conference name provided.");
03028       return 0;
03029    }
03030    if (!ao2_container_count(conference_bridges)) {
03031       astman_send_error(s, m, "No active conferences.");
03032       return 0;
03033    }
03034 
03035    conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
03036    if (!conference) {
03037       astman_send_error(s, m, "No Conference by that name found.");
03038       return 0;
03039    }
03040 
03041    found = !kick_conference_participant(conference, channel);
03042    ao2_ref(conference, -1);
03043 
03044    if (found) {
03045       astman_send_ack(s, m, !strcmp("all", channel) ? "All participants kicked" : "User kicked");
03046    } else {
03047       astman_send_error(s, m, "No Channel by that name found in Conference.");
03048    }
03049    return 0;
03050 }

static int action_confbridgelist ( struct mansession s,
const struct message m 
) [static]

Definition at line 2851 of file app_confbridge.c.

References action_confbridgelist_item(), confbridge_conference::active_list, ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, AST_LIST_TRAVERSE, ast_strlen_zero, astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), OBJ_KEY, total, and confbridge_conference::waiting_list.

Referenced by load_module().

02852 {
02853    const char *actionid = astman_get_header(m, "ActionID");
02854    const char *conference_name = astman_get_header(m, "Conference");
02855    struct confbridge_user *user;
02856    struct confbridge_conference *conference;
02857    char id_text[80];
02858    int total = 0;
02859 
02860    id_text[0] = '\0';
02861    if (!ast_strlen_zero(actionid)) {
02862       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
02863    }
02864    if (ast_strlen_zero(conference_name)) {
02865       astman_send_error(s, m, "No Conference name provided.");
02866       return 0;
02867    }
02868    if (!ao2_container_count(conference_bridges)) {
02869       astman_send_error(s, m, "No active conferences.");
02870       return 0;
02871    }
02872    conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
02873    if (!conference) {
02874       astman_send_error(s, m, "No Conference by that name found.");
02875       return 0;
02876    }
02877 
02878    astman_send_listack(s, m, "Confbridge user list will follow", "start");
02879 
02880    ao2_lock(conference);
02881    AST_LIST_TRAVERSE(&conference->active_list, user, list) {
02882       total++;
02883       action_confbridgelist_item(s, id_text, conference, user, 0);
02884    }
02885    AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
02886       total++;
02887       action_confbridgelist_item(s, id_text, conference, user, 1);
02888    }
02889    ao2_unlock(conference);
02890    ao2_ref(conference, -1);
02891 
02892    astman_send_list_complete_start(s, m, "ConfbridgeListComplete", total);
02893    astman_send_list_complete_end(s);
02894 
02895    return 0;
02896 }

static void action_confbridgelist_item ( struct mansession s,
const char *  id_text,
struct confbridge_conference conference,
struct confbridge_user user,
int  waiting 
) [static]

Definition at line 2820 of file app_confbridge.c.

References ast_channel_caller(), ast_channel_get_up_time(), ast_channel_name(), ast_test_flag, astman_append(), confbridge_user::chan, ast_party_caller::id, confbridge_user::muted, ast_party_id::name, confbridge_conference::name, ast_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, confbridge_user::u_profile, USER_OPT_ADMIN, USER_OPT_ENDMARKED, USER_OPT_MARKEDUSER, USER_OPT_WAITMARKED, ast_party_name::valid, and ast_party_number::valid.

Referenced by action_confbridgelist().

02821 {
02822    astman_append(s,
02823       "Event: ConfbridgeList\r\n"
02824       "%s"
02825       "Conference: %s\r\n"
02826       "CallerIDNum: %s\r\n"
02827       "CallerIDName: %s\r\n"
02828       "Channel: %s\r\n"
02829       "Admin: %s\r\n"
02830       "MarkedUser: %s\r\n"
02831       "WaitMarked: %s\r\n"
02832       "EndMarked: %s\r\n"
02833       "Waiting: %s\r\n"
02834       "Muted: %s\r\n"
02835       "AnsweredTime: %d\r\n"
02836       "\r\n",
02837       id_text,
02838       conference->name,
02839       S_COR(ast_channel_caller(user->chan)->id.number.valid, ast_channel_caller(user->chan)->id.number.str, "<unknown>"),
02840       S_COR(ast_channel_caller(user->chan)->id.name.valid, ast_channel_caller(user->chan)->id.name.str, "<no name>"),
02841       ast_channel_name(user->chan),
02842       ast_test_flag(&user->u_profile, USER_OPT_ADMIN) ? "Yes" : "No",
02843       ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No",
02844       ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED) ? "Yes" : "No",
02845       ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED) ? "Yes" : "No",
02846       waiting ? "Yes" : "No",
02847       user->muted ? "Yes" : "No",
02848       ast_channel_get_up_time(user->chan));
02849 }

static int action_confbridgelistrooms ( struct mansession s,
const struct message m 
) [static]

Definition at line 2898 of file app_confbridge.c.

References confbridge_conference::activeusers, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_strlen_zero, astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), confbridge_conference::locked, confbridge_conference::markedusers, confbridge_conference::name, and confbridge_conference::waitingusers.

Referenced by load_module().

02899 {
02900    const char *actionid = astman_get_header(m, "ActionID");
02901    struct confbridge_conference *conference;
02902    struct ao2_iterator iter;
02903    char id_text[512] = "";
02904    int totalitems = 0;
02905 
02906    if (!ast_strlen_zero(actionid)) {
02907       snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid);
02908    }
02909 
02910    if (!ao2_container_count(conference_bridges)) {
02911       astman_send_error(s, m, "No active conferences.");
02912       return 0;
02913    }
02914 
02915    astman_send_listack(s, m, "Confbridge conferences will follow", "start");
02916 
02917    /* Traverse the conference list */
02918    iter = ao2_iterator_init(conference_bridges, 0);
02919    while ((conference = ao2_iterator_next(&iter))) {
02920       totalitems++;
02921 
02922       ao2_lock(conference);
02923       astman_append(s,
02924       "Event: ConfbridgeListRooms\r\n"
02925       "%s"
02926       "Conference: %s\r\n"
02927       "Parties: %u\r\n"
02928       "Marked: %u\r\n"
02929       "Locked: %s\r\n"
02930       "\r\n",
02931       id_text,
02932       conference->name,
02933       conference->activeusers + conference->waitingusers,
02934       conference->markedusers,
02935       conference->locked ? "Yes" : "No");
02936       ao2_unlock(conference);
02937 
02938       ao2_ref(conference, -1);
02939    }
02940    ao2_iterator_destroy(&iter);
02941 
02942    /* Send final confirmation */
02943    astman_send_list_complete_start(s, m, "ConfbridgeListRoomsComplete", totalitems);
02944    astman_send_list_complete_end(s);
02945    return 0;
02946 }

static int action_confbridgelock ( struct mansession s,
const struct message m 
) [static]

Definition at line 3014 of file app_confbridge.c.

References action_lock_unlock_helper().

Referenced by load_module().

03015 {
03016    return action_lock_unlock_helper(s, m, 1);
03017 }

static int action_confbridgemute ( struct mansession s,
const struct message m 
) [static]

Definition at line 2985 of file app_confbridge.c.

References action_mute_unmute_helper().

Referenced by load_module().

02986 {
02987    return action_mute_unmute_helper(s, m, 1);
02988 }

static int action_confbridgesetsinglevideosrc ( struct mansession s,
const struct message m 
) [static]

Definition at line 3131 of file app_confbridge.c.

References confbridge_conference::active_list, ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_bridge_set_single_src_video_mode(), ast_channel_name(), AST_LIST_TRAVERSE, ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), confbridge_conference::bridge, confbridge_user::chan, and OBJ_KEY.

Referenced by load_module().

03132 {
03133    const char *conference_name = astman_get_header(m, "Conference");
03134    const char *channel = astman_get_header(m, "Channel");
03135    struct confbridge_user *user;
03136    struct confbridge_conference *conference;
03137 
03138    if (ast_strlen_zero(conference_name)) {
03139       astman_send_error(s, m, "No Conference name provided.");
03140       return 0;
03141    }
03142    if (ast_strlen_zero(channel)) {
03143       astman_send_error(s, m, "No channel name provided.");
03144       return 0;
03145    }
03146    if (!ao2_container_count(conference_bridges)) {
03147       astman_send_error(s, m, "No active conferences.");
03148       return 0;
03149    }
03150 
03151    conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
03152    if (!conference) {
03153       astman_send_error(s, m, "No Conference by that name found.");
03154       return 0;
03155    }
03156 
03157    /* find channel and set as video src. */
03158    ao2_lock(conference);
03159    AST_LIST_TRAVERSE(&conference->active_list, user, list) {
03160       if (!strncmp(channel, ast_channel_name(user->chan), strlen(channel))) {
03161          ast_bridge_set_single_src_video_mode(conference->bridge, user->chan);
03162          break;
03163       }
03164    }
03165    ao2_unlock(conference);
03166    ao2_ref(conference, -1);
03167 
03168    /* do not access user after conference unlock.  We are just
03169     * using this check to see if it was found or not */
03170    if (!user) {
03171       astman_send_error(s, m, "No channel by that name found in conference.");
03172       return 0;
03173    }
03174    astman_send_ack(s, m, "Conference single video source set.");
03175    return 0;
03176 }

static int action_confbridgestartrecord ( struct mansession s,
const struct message m 
) [static]

Definition at line 3052 of file app_confbridge.c.

References ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), confbridge_conference::b_profile, conf_is_recording(), conf_start_record(), OBJ_KEY, and bridge_profile::rec_file.

Referenced by load_module().

03053 {
03054    const char *conference_name = astman_get_header(m, "Conference");
03055    const char *recordfile = astman_get_header(m, "RecordFile");
03056    struct confbridge_conference *conference;
03057 
03058    if (ast_strlen_zero(conference_name)) {
03059       astman_send_error(s, m, "No Conference name provided.");
03060       return 0;
03061    }
03062    if (!ao2_container_count(conference_bridges)) {
03063       astman_send_error(s, m, "No active conferences.");
03064       return 0;
03065    }
03066 
03067    conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
03068    if (!conference) {
03069       astman_send_error(s, m, "No Conference by that name found.");
03070       return 0;
03071    }
03072 
03073    ao2_lock(conference);
03074    if (conf_is_recording(conference)) {
03075       astman_send_error(s, m, "Conference is already being recorded.");
03076       ao2_unlock(conference);
03077       ao2_ref(conference, -1);
03078       return 0;
03079    }
03080 
03081    if (!ast_strlen_zero(recordfile)) {
03082       ast_copy_string(conference->b_profile.rec_file, recordfile, sizeof(conference->b_profile.rec_file));
03083    }
03084 
03085    if (conf_start_record(conference)) {
03086       astman_send_error(s, m, "Internal error starting conference recording.");
03087       ao2_unlock(conference);
03088       ao2_ref(conference, -1);
03089       return 0;
03090    }
03091    ao2_unlock(conference);
03092 
03093    ao2_ref(conference, -1);
03094    astman_send_ack(s, m, "Conference Recording Started.");
03095    return 0;
03096 }

static int action_confbridgestoprecord ( struct mansession s,
const struct message m 
) [static]

Definition at line 3097 of file app_confbridge.c.

References ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), conf_stop_record(), and OBJ_KEY.

Referenced by load_module().

03098 {
03099    const char *conference_name = astman_get_header(m, "Conference");
03100    struct confbridge_conference *conference;
03101 
03102    if (ast_strlen_zero(conference_name)) {
03103       astman_send_error(s, m, "No Conference name provided.");
03104       return 0;
03105    }
03106    if (!ao2_container_count(conference_bridges)) {
03107       astman_send_error(s, m, "No active conferences.");
03108       return 0;
03109    }
03110 
03111    conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
03112    if (!conference) {
03113       astman_send_error(s, m, "No Conference by that name found.");
03114       return 0;
03115    }
03116 
03117    ao2_lock(conference);
03118    if (conf_stop_record(conference)) {
03119       ao2_unlock(conference);
03120       astman_send_error(s, m, "Internal error while stopping recording.");
03121       ao2_ref(conference, -1);
03122       return 0;
03123    }
03124    ao2_unlock(conference);
03125 
03126    ao2_ref(conference, -1);
03127    astman_send_ack(s, m, "Conference Recording Stopped.");
03128    return 0;
03129 }

static int action_confbridgeunlock ( struct mansession s,
const struct message m 
) [static]

Definition at line 3010 of file app_confbridge.c.

References action_lock_unlock_helper().

Referenced by load_module().

03011 {
03012    return action_lock_unlock_helper(s, m, 0);
03013 }

static int action_confbridgeunmute ( struct mansession s,
const struct message m 
) [static]

Definition at line 2981 of file app_confbridge.c.

References action_mute_unmute_helper().

Referenced by load_module().

02982 {
02983    return action_mute_unmute_helper(s, m, 0);
02984 }

static int action_dialplan_exec ( struct ast_bridge_channel bridge_channel,
struct conf_menu_action menu_action 
) [static]

Definition at line 2046 of file app_confbridge.c.

References ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_lock, ast_channel_pbx(), ast_channel_pbx_set(), ast_channel_priority(), ast_channel_priority_set(), ast_channel_unlock, ast_pbx_run_args(), ast_strdupa, ast_bridge_channel::chan, context, conf_menu_action::data, conf_menu_action::dialplan_args, exten, ast_pbx_args::no_hangup_chan, and NULL.

Referenced by execute_menu_entry().

02047 {
02048    struct ast_pbx_args args;
02049    struct ast_pbx *pbx;
02050    char *exten;
02051    char *context;
02052    int priority;
02053    int res;
02054 
02055    memset(&args, 0, sizeof(args));
02056    args.no_hangup_chan = 1;
02057 
02058    ast_channel_lock(bridge_channel->chan);
02059 
02060    /*save off*/
02061    exten = ast_strdupa(ast_channel_exten(bridge_channel->chan));
02062    context = ast_strdupa(ast_channel_context(bridge_channel->chan));
02063    priority = ast_channel_priority(bridge_channel->chan);
02064    pbx = ast_channel_pbx(bridge_channel->chan);
02065    ast_channel_pbx_set(bridge_channel->chan, NULL);
02066 
02067    /*set new*/
02068    ast_channel_exten_set(bridge_channel->chan, menu_action->data.dialplan_args.exten);
02069    ast_channel_context_set(bridge_channel->chan, menu_action->data.dialplan_args.context);
02070    ast_channel_priority_set(bridge_channel->chan, menu_action->data.dialplan_args.priority);
02071 
02072    ast_channel_unlock(bridge_channel->chan);
02073 
02074    /*execute*/
02075    res = ast_pbx_run_args(bridge_channel->chan, &args);
02076 
02077    /*restore*/
02078    ast_channel_lock(bridge_channel->chan);
02079 
02080    ast_channel_exten_set(bridge_channel->chan, exten);
02081    ast_channel_context_set(bridge_channel->chan, context);
02082    ast_channel_priority_set(bridge_channel->chan, priority);
02083    ast_channel_pbx_set(bridge_channel->chan, pbx);
02084 
02085    ast_channel_unlock(bridge_channel->chan);
02086 
02087    return res;
02088 }

static int action_kick_last ( struct confbridge_conference conference,
struct ast_bridge_channel bridge_channel,
struct confbridge_user user 
) [static]

Definition at line 2015 of file app_confbridge.c.

References confbridge_conference::active_list, ao2_lock, ao2_unlock, ast_bridge_remove(), ast_channel_name(), AST_LIST_LAST, ast_log, ast_test_flag, confbridge_user::b_profile, confbridge_conference::bridge, confbridge_user::chan, ast_bridge_channel::chan, conf_get_sound(), CONF_SOUND_ERROR_MENU, confbridge_user::kicked, LOG_WARNING, confbridge_conference::name, NULL, pbx_builtin_setvar_helper(), play_file(), bridge_profile::sounds, confbridge_user::u_profile, and USER_OPT_ADMIN.

Referenced by execute_menu_entry().

02018 {
02019    struct confbridge_user *last_user = NULL;
02020    int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
02021 
02022    if (!isadmin) {
02023       play_file(bridge_channel, NULL,
02024            conf_get_sound(CONF_SOUND_ERROR_MENU, user->b_profile.sounds));
02025       ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
02026          ast_channel_name(bridge_channel->chan),
02027          conference->name);
02028       return -1;
02029    }
02030 
02031    ao2_lock(conference);
02032    if (((last_user = AST_LIST_LAST(&conference->active_list)) == user)
02033       || (ast_test_flag(&last_user->u_profile, USER_OPT_ADMIN))) {
02034       ao2_unlock(conference);
02035       play_file(bridge_channel, NULL,
02036            conf_get_sound(CONF_SOUND_ERROR_MENU, user->b_profile.sounds));
02037    } else if (last_user && !last_user->kicked) {
02038       last_user->kicked = 1;
02039       pbx_builtin_setvar_helper(last_user->chan, "CONFBRIDGE_RESULT", "KICKED");
02040       ast_bridge_remove(conference->bridge, last_user->chan);
02041       ao2_unlock(conference);
02042    }
02043    return 0;
02044 }

static int action_lock_unlock_helper ( struct mansession s,
const struct message m,
int  lock 
) [static]

Definition at line 2990 of file app_confbridge.c.

References ao2_container_count(), ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), and generic_lock_unlock_helper().

Referenced by action_confbridgelock(), and action_confbridgeunlock().

02991 {
02992    const char *conference_name = astman_get_header(m, "Conference");
02993    int res = 0;
02994 
02995    if (ast_strlen_zero(conference_name)) {
02996       astman_send_error(s, m, "No Conference name provided.");
02997       return 0;
02998    }
02999    if (!ao2_container_count(conference_bridges)) {
03000       astman_send_error(s, m, "No active conferences.");
03001       return 0;
03002    }
03003    if ((res = generic_lock_unlock_helper(lock, conference_name))) {
03004       astman_send_error(s, m, "No Conference by that name found.");
03005       return 0;
03006    }
03007    astman_send_ack(s, m, lock ? "Conference locked" : "Conference unlocked");
03008    return 0;
03009 }

static int action_mute_unmute_helper ( struct mansession s,
const struct message m,
int  mute 
) [static]

Definition at line 2948 of file app_confbridge.c.

References ao2_container_count(), ast_strlen_zero, astman_get_header(), astman_send_ack(), astman_send_error(), and generic_mute_unmute_helper().

Referenced by action_confbridgemute(), and action_confbridgeunmute().

02949 {
02950    const char *conference_name = astman_get_header(m, "Conference");
02951    const char *channel_name = astman_get_header(m, "Channel");
02952    int res = 0;
02953 
02954    if (ast_strlen_zero(conference_name)) {
02955       astman_send_error(s, m, "No Conference name provided.");
02956       return 0;
02957    }
02958    if (ast_strlen_zero(channel_name)) {
02959       astman_send_error(s, m, "No channel name provided.");
02960       return 0;
02961    }
02962    if (!ao2_container_count(conference_bridges)) {
02963       astman_send_error(s, m, "No active conferences.");
02964       return 0;
02965    }
02966 
02967    res = generic_mute_unmute_helper(mute, conference_name, channel_name);
02968 
02969    if (res == -1) {
02970       astman_send_error(s, m, "No Conference by that name found.");
02971       return 0;
02972    } else if (res == -2) {
02973       astman_send_error(s, m, "No Channel by that name found in Conference.");
02974       return 0;
02975    }
02976 
02977    astman_send_ack(s, m, mute ? "User muted" : "User unmuted");
02978    return 0;
02979 }

static int action_playback ( struct ast_bridge_channel bridge_channel,
const char *  playback_file 
) [static]

Definition at line 1930 of file app_confbridge.c.

References ast_log, ast_strdupa, ast_stream_and_wait(), ast_bridge_channel::chan, LOG_WARNING, NULL, and strsep().

Referenced by execute_menu_entry().

01931 {
01932    char *file_copy = ast_strdupa(playback_file);
01933    char *file = NULL;
01934 
01935    while ((file = strsep(&file_copy, "&"))) {
01936       if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
01937          ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
01938          return -1;
01939       }
01940    }
01941    return 0;
01942 }

static int action_playback_and_continue ( struct confbridge_conference conference,
struct confbridge_user user,
struct ast_bridge_channel bridge_channel,
struct conf_menu menu,
const char *  playback_file,
const char *  cur_dtmf,
int *  stop_prompts 
) [static]

Definition at line 1944 of file app_confbridge.c.

References ast_channel_language(), ast_copy_string(), AST_DIGIT_ANY, ast_log, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_waitstream(), ast_bridge_channel::chan, conf_find_menu_entry_by_sequence(), conf_menu_entry_destroy(), digit, execute_menu_entry(), LOG_WARNING, MAXIMUM_DTMF_FEATURE_STRING, NULL, and strsep().

Referenced by execute_menu_entry().

01951 {
01952    int i;
01953    int digit = 0;
01954    char dtmf[MAXIMUM_DTMF_FEATURE_STRING];
01955    struct conf_menu_entry new_menu_entry = { { 0, }, };
01956    char *file_copy = ast_strdupa(playback_file);
01957    char *file = NULL;
01958 
01959    while ((file = strsep(&file_copy, "&"))) {
01960       if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) {
01961          ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
01962          return -1;
01963       }
01964 
01965       /* now wait for more digits. */
01966       if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) {
01967          /* streaming finished and no DTMF was entered */
01968          continue;
01969       } else if (digit == -1) {
01970          /* error */
01971          return -1;
01972       } else {
01973          break; /* dtmf was entered */
01974       }
01975    }
01976    if (!digit) {
01977       /* streaming finished on all files and no DTMF was entered */
01978       return -1;
01979    }
01980    ast_stopstream(bridge_channel->chan);
01981 
01982    /* If we get here, then DTMF has been entered, This means no
01983     * additional prompts should be played for this menu entry */
01984    *stop_prompts = 1;
01985 
01986    /* If a digit was pressed during the payback, update
01987     * the dtmf string and look for a new menu entry in the
01988     * menu structure */
01989    ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf));
01990    for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) {
01991       dtmf[i] = cur_dtmf[i];
01992       if (!dtmf[i]) {
01993          dtmf[i] = (char) digit;
01994          dtmf[i + 1] = '\0';
01995          i = -1;
01996          break;
01997       }
01998    }
01999    /* If i is not -1 then the new dtmf digit was _NOT_ added to the string.
02000     * If this is the case, no new DTMF sequence should be looked for. */
02001    if (i != -1) {
02002       return 0;
02003    }
02004 
02005    if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) {
02006       execute_menu_entry(conference,
02007          user,
02008          bridge_channel,
02009          &new_menu_entry, menu);
02010       conf_menu_entry_destroy(&new_menu_entry);
02011    }
02012    return 0;
02013 }

static int action_toggle_mute ( struct confbridge_conference conference,
struct confbridge_user user,
struct ast_bridge_channel bridge_channel 
) [static]

Definition at line 1864 of file app_confbridge.c.

References ast_channel_name(), ast_test_suite_event_notify, confbridge_user::b_profile, confbridge_user::chan, conf_get_sound(), CONF_SOUND_MUTED, CONF_SOUND_UNMUTED, conf_update_user_mute(), mute, confbridge_user::muted, bridge_profile::name, NULL, play_file(), send_mute_event(), send_unmute_event(), and bridge_profile::sounds.

Referenced by execute_menu_entry().

01867 {
01868    int mute;
01869 
01870    /* Toggle user level mute request. */
01871    mute = !user->muted;
01872    user->muted = mute;
01873 
01874    conf_update_user_mute(user);
01875    ast_test_suite_event_notify("CONF_MUTE",
01876       "Message: participant %s %s\r\n"
01877       "Conference: %s\r\n"
01878       "Channel: %s",
01879       ast_channel_name(user->chan),
01880       mute ? "muted" : "unmuted",
01881       user->b_profile.name,
01882       ast_channel_name(user->chan));
01883    if (mute) {
01884       send_mute_event(user, conference);
01885    } else {
01886       send_unmute_event(user, conference);
01887    }
01888 
01889    return play_file(bridge_channel, NULL, (mute ?
01890       conf_get_sound(CONF_SOUND_MUTED, user->b_profile.sounds) :
01891       conf_get_sound(CONF_SOUND_UNMUTED, user->b_profile.sounds))) < 0;
01892 }

static int action_toggle_mute_participants ( struct confbridge_conference conference,
struct confbridge_user user 
) [static]

Definition at line 1894 of file app_confbridge.c.

References confbridge_conference::active_list, ao2_lock, ao2_unlock, ast_autoservice_start(), ast_autoservice_stop(), AST_LIST_TRAVERSE, ast_stream_and_wait(), ast_test_flag, confbridge_user::b_profile, confbridge_user::chan, conf_get_sound(), CONF_SOUND_PARTICIPANTS_MUTED, CONF_SOUND_PARTICIPANTS_UNMUTED, conf_update_user_mute(), confbridge_user::list, mute, confbridge_user::muted, confbridge_conference::muted, NULL, play_sound_helper(), bridge_profile::sounds, confbridge_user::u_profile, and USER_OPT_ADMIN.

Referenced by execute_menu_entry().

01895 {
01896    struct confbridge_user *cur_user = NULL;
01897    const char *sound_to_play;
01898    int mute;
01899 
01900    ao2_lock(conference);
01901 
01902    /* Toggle bridge level mute request. */
01903    mute = !conference->muted;
01904    conference->muted = mute;
01905 
01906    AST_LIST_TRAVERSE(&conference->active_list, cur_user, list) {
01907       if (!ast_test_flag(&cur_user->u_profile, USER_OPT_ADMIN)) {
01908          /* Set user level to bridge level mute request. */
01909          cur_user->muted = mute;
01910          conf_update_user_mute(cur_user);
01911       }
01912    }
01913 
01914    ao2_unlock(conference);
01915 
01916    sound_to_play = conf_get_sound((mute ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED),
01917       user->b_profile.sounds);
01918 
01919    /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
01920    ast_stream_and_wait(user->chan, sound_to_play, "");
01921 
01922    /* Announce to the group that all participants are muted */
01923    ast_autoservice_start(user->chan);
01924    play_sound_helper(conference, sound_to_play, 0);
01925    ast_autoservice_stop(user->chan);
01926 
01927    return 0;
01928 }

static int alloc_playback_chan ( struct confbridge_conference conference  )  [static]

Definition at line 1408 of file app_confbridge.c.

References ao2_ref, ast_channel_lock, ast_channel_name(), ast_channel_unlock, ast_debug, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_request(), confbridge_conference::b_profile, bridge_profile::language, confbridge_conference::name, NULL, and confbridge_conference::playback_chan.

Referenced by play_sound_helper().

01409 {
01410    struct ast_format_cap *cap;
01411 
01412    cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
01413    if (!cap) {
01414       return -1;
01415    }
01416    ast_format_cap_append(cap, ast_format_slin, 0);
01417    conference->playback_chan = ast_request("CBAnn", cap, NULL, NULL,
01418       conference->name, NULL);
01419    ao2_ref(cap, -1);
01420    if (!conference->playback_chan) {
01421       return -1;
01422    }
01423 
01424    /* To make sure playback_chan has the same language of that profile */
01425    ast_channel_lock(conference->playback_chan);
01426    ast_channel_language_set(conference->playback_chan, conference->b_profile.language);
01427    ast_channel_unlock(conference->playback_chan);
01428 
01429    ast_debug(1, "Created announcer channel '%s' to conference bridge '%s'\n",
01430       ast_channel_name(conference->playback_chan), conference->name);
01431    return 0;
01432 }

static int announce_user_count ( struct confbridge_conference conference,
struct confbridge_user user,
struct ast_bridge_channel bridge_channel 
) [static]

Announce number of users in the conference bridge to the caller.

Parameters:
conference Conference bridge to peek at
user Optional Caller
bridge_channel The bridged channel involved
Note:
if caller is NULL, the announcment will be sent to all participants in the conference.
Returns:
Returns 0 on success, -1 if the user hung up

Definition at line 799 of file app_confbridge.c.

References confbridge_conference::activeusers, ast_channel_language(), ast_say_number(), ast_stream_and_wait(), confbridge_conference::b_profile, confbridge_user::chan, conf_get_sound(), CONF_SOUND_ONLY_ONE, CONF_SOUND_OTHER_IN_PARTY, CONF_SOUND_THERE_ARE, NULL, play_file(), play_sound_file(), play_sound_number(), sound_file_exists(), and bridge_profile::sounds.

Referenced by execute_menu_entry(), and join_conference_bridge().

00801 {
00802    const char *other_in_party = conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, conference->b_profile.sounds);
00803    const char *only_one = conf_get_sound(CONF_SOUND_ONLY_ONE, conference->b_profile.sounds);
00804    const char *there_are = conf_get_sound(CONF_SOUND_THERE_ARE, conference->b_profile.sounds);
00805 
00806    if (conference->activeusers <= 1) {
00807       /* Awww we are the only person in the conference bridge OR we only have waitmarked users */
00808       return 0;
00809    } else if (conference->activeusers == 2) {
00810       if (user) {
00811          /* Eep, there is one other person */
00812          if (play_file(bridge_channel, user->chan, only_one) < 0) {
00813             return -1;
00814          }
00815       } else {
00816          play_sound_file(conference, only_one);
00817       }
00818    } else {
00819       /* Alas multiple others in here */
00820       if (user) {
00821          if (ast_stream_and_wait(user->chan,
00822             there_are,
00823             "")) {
00824             return -1;
00825          }
00826          if (ast_say_number(user->chan, conference->activeusers - 1, "", ast_channel_language(user->chan), NULL)) {
00827             return -1;
00828          }
00829          if (play_file(bridge_channel, user->chan, other_in_party) < 0) {
00830             return -1;
00831          }
00832       } else if (sound_file_exists(there_are) && sound_file_exists(other_in_party)) {
00833          play_sound_file(conference, there_are);
00834          play_sound_number(conference, conference->activeusers - 1);
00835          play_sound_file(conference, other_in_party);
00836       }
00837    }
00838    return 0;
00839 }

static int cli_mute_unmute_helper ( int  mute,
struct ast_cli_args a 
) [static]

Definition at line 2573 of file app_confbridge.c.

References ast_cli_args::argv, ast_cli(), ast_cli_args::fd, and generic_mute_unmute_helper().

Referenced by handle_cli_confbridge_mute(), and handle_cli_confbridge_unmute().

02574 {
02575    int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]);
02576 
02577    if (res == -1) {
02578       ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
02579       return -1;
02580    } else if (res == -2) {
02581       if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
02582          ast_cli(a->fd, "No participants found in conference %s\n", a->argv[2]);
02583       } else {
02584          ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]);
02585       }
02586       return -1;
02587    }
02588    ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]);
02589    return 0;
02590 }

static char* complete_confbridge_name ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 2260 of file app_confbridge.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_strdup, confbridge_conference::name, and NULL.

Referenced by handle_cli_confbridge_kick(), handle_cli_confbridge_list(), handle_cli_confbridge_lock(), handle_cli_confbridge_mute(), handle_cli_confbridge_start_record(), handle_cli_confbridge_stop_record(), handle_cli_confbridge_unlock(), and handle_cli_confbridge_unmute().

02261 {
02262    int which = 0;
02263    struct confbridge_conference *conference;
02264    char *res = NULL;
02265    int wordlen = strlen(word);
02266    struct ao2_iterator iter;
02267 
02268    iter = ao2_iterator_init(conference_bridges, 0);
02269    while ((conference = ao2_iterator_next(&iter))) {
02270       if (!strncasecmp(conference->name, word, wordlen) && ++which > state) {
02271          res = ast_strdup(conference->name);
02272          ao2_ref(conference, -1);
02273          break;
02274       }
02275       ao2_ref(conference, -1);
02276    }
02277    ao2_iterator_destroy(&iter);
02278 
02279    return res;
02280 }

static char* complete_confbridge_participant ( const char *  conference_name,
const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 2282 of file app_confbridge.c.

References confbridge_conference::active_list, ao2_cleanup, ao2_find, ast_channel_name(), AST_LIST_TRAVERSE, ast_strdup, confbridge_user::chan, confbridge_user::conference, confbridge_user::list, NULL, OBJ_KEY, RAII_VAR, SCOPED_AO2LOCK, and confbridge_conference::waiting_list.

Referenced by handle_cli_confbridge_kick(), handle_cli_confbridge_mute(), and handle_cli_confbridge_unmute().

02283 {
02284    int which = 0;
02285    RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
02286    struct confbridge_user *user;
02287    char *res = NULL;
02288    int wordlen = strlen(word);
02289 
02290    conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
02291    if (!conference) {
02292       return NULL;
02293    }
02294 
02295    if (!strncasecmp("all", word, wordlen) && ++which > state) {
02296       return ast_strdup("all");
02297    }
02298 
02299    if (!strncasecmp("participants", word, wordlen) && ++which > state) {
02300       return ast_strdup("participants");
02301    }
02302 
02303    {
02304       SCOPED_AO2LOCK(bridge_lock, conference);
02305       AST_LIST_TRAVERSE(&conference->active_list, user, list) {
02306          if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
02307             res = ast_strdup(ast_channel_name(user->chan));
02308             return res;
02309          }
02310       }
02311       AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
02312          if (!strncasecmp(ast_channel_name(user->chan), word, wordlen) && ++which > state) {
02313             res = ast_strdup(ast_channel_name(user->chan));
02314             return res;
02315          }
02316       }
02317    }
02318 
02319    return NULL;
02320 }

int conf_add_post_join_action ( struct confbridge_user user,
int(*)(struct confbridge_user *user func 
)

Queue a function to run with the given conference bridge user as an argument once the state transition is complete.

Parameters:
user The conference bridge user to pass to the function
func The function to queue
Return values:
0 success
non-zero failure

Definition at line 1166 of file app_confbridge.c.

References ast_calloc, AST_LIST_INSERT_TAIL, func, post_join_action::func, post_join_action::list, and confbridge_user::post_join_list.

Referenced by conf_default_join_waitmarked(), join_unmarked(), and transition_to_marked().

01167 {
01168    struct post_join_action *action;
01169    if (!(action = ast_calloc(1, sizeof(*action)))) {
01170       return -1;
01171    }
01172    action->func = func;
01173    AST_LIST_INSERT_TAIL(&user->post_join_list, action, list);
01174    return 0;
01175 }

void conf_add_user_active ( struct confbridge_conference conference,
struct confbridge_user user 
)

Add a conference bridge user as an unmarked active user of the conference.

Parameters:
conference The conference bridge to add the user to
user The conference bridge user to add to the conference

Definition at line 3237 of file app_confbridge.c.

References confbridge_conference::active_list, confbridge_conference::activeusers, AST_LIST_INSERT_TAIL, and confbridge_user::list.

Referenced by join_active(), and join_unmarked().

03238 {
03239    AST_LIST_INSERT_TAIL(&conference->active_list, user, list);
03240    conference->activeusers++;
03241 }

void conf_add_user_marked ( struct confbridge_conference conference,
struct confbridge_user user 
)

Add a conference bridge user as a marked active user of the conference.

Parameters:
conference The conference bridge to add the user to
user The conference bridge user to add to the conference

Definition at line 3243 of file app_confbridge.c.

References confbridge_conference::active_list, confbridge_conference::activeusers, AST_LIST_INSERT_TAIL, confbridge_user::list, and confbridge_conference::markedusers.

Referenced by join_marked().

03244 {
03245    AST_LIST_INSERT_TAIL(&conference->active_list, user, list);
03246    conference->activeusers++;
03247    conference->markedusers++;
03248 }

void conf_add_user_waiting ( struct confbridge_conference conference,
struct confbridge_user user 
)

Add a conference bridge user as an waiting user of the conference.

Parameters:
conference The conference bridge to add the user to
user The conference bridge user to add to the conference

Definition at line 3250 of file app_confbridge.c.

References AST_LIST_INSERT_TAIL, confbridge_user::list, confbridge_conference::waiting_list, and confbridge_conference::waitingusers.

Referenced by conf_default_join_waitmarked().

03251 {
03252    AST_LIST_INSERT_TAIL(&conference->waiting_list, user, list);
03253    conference->waitingusers++;
03254 }

void conf_ended ( struct confbridge_conference conference  ) 

Callback to be called when the conference has become empty.

Parameters:
conference The conference bridge

Definition at line 1194 of file app_confbridge.c.

References ao2_lock, ao2_unlink, ao2_unlock, conf_stop_record(), and send_conf_end_event().

Referenced by transition_to_empty().

01195 {
01196    /* Called with a reference to conference */
01197    ao2_unlink(conference_bridges, conference);
01198    send_conf_end_event(conference);
01199    ao2_lock(conference);
01200    conf_stop_record(conference);
01201    ao2_unlock(conference);
01202 }

static int conf_get_pin ( struct ast_channel chan,
struct confbridge_user user 
) [static]

Definition at line 1511 of file app_confbridge.c.

References ast_app_getdata(), ast_channel_language(), AST_DIGIT_ANY, ast_streamfile(), ast_waitstream(), confbridge_user::b_profile, conf_get_sound(), CONF_SOUND_GET_PIN, CONF_SOUND_INVALID_PIN, len(), MAX_PIN, user_profile::pin, bridge_profile::sounds, tmp(), and confbridge_user::u_profile.

Referenced by confbridge_exec().

01512 {
01513    char pin_guess[MAX_PIN+1] = { 0, };
01514    const char *pin = user->u_profile.pin;
01515    char *tmp = pin_guess;
01516    int i, res;
01517    unsigned int len = MAX_PIN ;
01518 
01519    /* give them three tries to get the pin right */
01520    for (i = 0; i < 3; i++) {
01521       if (ast_app_getdata(chan,
01522          conf_get_sound(CONF_SOUND_GET_PIN, user->b_profile.sounds),
01523          tmp, len, 0) >= 0) {
01524          if (!strcasecmp(pin, pin_guess)) {
01525             return 0;
01526          }
01527       }
01528       ast_streamfile(chan,
01529          conf_get_sound(CONF_SOUND_INVALID_PIN, user->b_profile.sounds),
01530          ast_channel_language(chan));
01531       res = ast_waitstream(chan, AST_DIGIT_ANY);
01532       if (res > 0) {
01533          /* Account for digit already read during ivalid pin playback
01534           * resetting pin buf. */
01535          pin_guess[0] = res;
01536          pin_guess[1] = '\0';
01537          tmp = pin_guess + 1;
01538          len = MAX_PIN - 1;
01539       } else {
01540          /* reset pin buf as empty buffer. */
01541          tmp = pin_guess;
01542          len = MAX_PIN;
01543       }
01544    }
01545    return -1;
01546 }

const char* conf_get_sound ( enum conf_sounds  sound,
struct bridge_profile_sounds custom_sounds 
)

Looks to see if sound file is stored in bridge profile sounds, if not default sound is provided.

Definition at line 391 of file app_confbridge.c.

References bridge_profile_sounds::begin, CONF_SOUND_BEGIN, CONF_SOUND_ERROR_MENU, CONF_SOUND_GET_PIN, CONF_SOUND_HAS_JOINED, CONF_SOUND_HAS_LEFT, CONF_SOUND_INVALID_PIN, CONF_SOUND_JOIN, CONF_SOUND_KICKED, CONF_SOUND_LEADER_HAS_LEFT, CONF_SOUND_LEAVE, CONF_SOUND_LOCKED, CONF_SOUND_LOCKED_NOW, CONF_SOUND_MUTED, CONF_SOUND_ONLY_ONE, CONF_SOUND_ONLY_PERSON, CONF_SOUND_OTHER_IN_PARTY, CONF_SOUND_PARTICIPANTS_MUTED, CONF_SOUND_PARTICIPANTS_UNMUTED, CONF_SOUND_PLACE_IN_CONF, CONF_SOUND_THERE_ARE, CONF_SOUND_UNLOCKED_NOW, CONF_SOUND_UNMUTED, CONF_SOUND_WAIT_FOR_LEADER, bridge_profile_sounds::errormenu, bridge_profile_sounds::getpin, bridge_profile_sounds::hasjoin, bridge_profile_sounds::hasleft, bridge_profile_sounds::invalidpin, bridge_profile_sounds::join, bridge_profile_sounds::kicked, bridge_profile_sounds::leaderhasleft, bridge_profile_sounds::leave, bridge_profile_sounds::locked, bridge_profile_sounds::lockednow, bridge_profile_sounds::muted, bridge_profile_sounds::onlyone, bridge_profile_sounds::onlyperson, bridge_profile_sounds::otherinparty, bridge_profile_sounds::participantsmuted, bridge_profile_sounds::participantsunmuted, bridge_profile_sounds::placeintoconf, S_OR, bridge_profile_sounds::thereare, bridge_profile_sounds::unlockednow, bridge_profile_sounds::unmuted, and bridge_profile_sounds::waitforleader.

Referenced by action_kick_last(), action_toggle_mute(), action_toggle_mute_participants(), announce_user_count(), conf_get_pin(), conf_handle_inactive_waitmarked(), conf_handle_only_unmarked(), confbridge_exec(), execute_menu_entry(), handle_cli_confbridge_show_bridge_profile(), join_conference_bridge(), leave_marked(), and post_join_play_begin().

00392 {
00393    switch (sound) {
00394    case CONF_SOUND_HAS_JOINED:
00395       return S_OR(custom_sounds->hasjoin, "conf-hasjoin");
00396    case CONF_SOUND_HAS_LEFT:
00397       return S_OR(custom_sounds->hasleft, "conf-hasleft");
00398    case CONF_SOUND_KICKED:
00399       return S_OR(custom_sounds->kicked, "conf-kicked");
00400    case CONF_SOUND_MUTED:
00401       return S_OR(custom_sounds->muted, "conf-muted");
00402    case CONF_SOUND_UNMUTED:
00403       return S_OR(custom_sounds->unmuted, "conf-unmuted");
00404    case CONF_SOUND_ONLY_ONE:
00405       return S_OR(custom_sounds->onlyone, "conf-onlyone");
00406    case CONF_SOUND_THERE_ARE:
00407       return S_OR(custom_sounds->thereare, "conf-thereare");
00408    case CONF_SOUND_OTHER_IN_PARTY:
00409       return S_OR(custom_sounds->otherinparty, "conf-otherinparty");
00410    case CONF_SOUND_PLACE_IN_CONF:
00411       return S_OR(custom_sounds->placeintoconf, "conf-placeintoconf");
00412    case CONF_SOUND_WAIT_FOR_LEADER:
00413       return S_OR(custom_sounds->waitforleader, "conf-waitforleader");
00414    case CONF_SOUND_LEADER_HAS_LEFT:
00415       return S_OR(custom_sounds->leaderhasleft, "conf-leaderhasleft");
00416    case CONF_SOUND_GET_PIN:
00417       return S_OR(custom_sounds->getpin, "conf-getpin");
00418    case CONF_SOUND_INVALID_PIN:
00419       return S_OR(custom_sounds->invalidpin, "conf-invalidpin");
00420    case CONF_SOUND_ONLY_PERSON:
00421       return S_OR(custom_sounds->onlyperson, "conf-onlyperson");
00422    case CONF_SOUND_LOCKED:
00423       return S_OR(custom_sounds->locked, "conf-locked");
00424    case CONF_SOUND_LOCKED_NOW:
00425       return S_OR(custom_sounds->lockednow, "conf-lockednow");
00426    case CONF_SOUND_UNLOCKED_NOW:
00427       return S_OR(custom_sounds->unlockednow, "conf-unlockednow");
00428    case CONF_SOUND_ERROR_MENU:
00429       return S_OR(custom_sounds->errormenu, "conf-errormenu");
00430    case CONF_SOUND_JOIN:
00431       return S_OR(custom_sounds->join, "confbridge-join");
00432    case CONF_SOUND_LEAVE:
00433       return S_OR(custom_sounds->leave, "confbridge-leave");
00434    case CONF_SOUND_PARTICIPANTS_MUTED:
00435       return S_OR(custom_sounds->participantsmuted, "conf-now-muted");
00436    case CONF_SOUND_PARTICIPANTS_UNMUTED:
00437       return S_OR(custom_sounds->participantsunmuted, "conf-now-unmuted");
00438    case CONF_SOUND_BEGIN:
00439       return S_OR(custom_sounds->begin, "confbridge-conf-begin");
00440    }
00441 
00442    return "";
00443 }

int conf_handle_dtmf ( struct ast_bridge_channel bridge_channel,
struct confbridge_user user,
struct conf_menu_entry menu_entry,
struct conf_menu menu 
)

Once a DTMF sequence matches a sequence in the user's DTMF menu, this function will get called to perform the menu action.

Parameters:
bridge_channel Bridged channel this is involving
user the conference user to perform the action on.
menu_entry the menu entry that invoked this callback to occur.
menu an AO2 referenced pointer to the entire menu structure the menu_entry derived from.
Note:
The menu_entry is a deep copy of the entry found in the menu structure. This allows for the menu_entry to be accessed without requiring the menu lock. If the menu must be accessed, the menu lock must be held. Reference counting of the menu structure is handled outside of the scope of this function.
Return values:
0 success
-1 failure

Definition at line 2196 of file app_confbridge.c.

References conf_moh_suspend(), conf_moh_unsuspend(), confbridge_user::conference, and execute_menu_entry().

Referenced by menu_hook_callback().

02200 {
02201    /* See if music on hold is playing */
02202    conf_moh_suspend(user);
02203 
02204    /* execute the list of actions associated with this menu entry */
02205    execute_menu_entry(user->conference, user, bridge_channel, menu_entry, menu);
02206 
02207    /* See if music on hold needs to be started back up again */
02208    conf_moh_unsuspend(user);
02209 
02210    return 0;
02211 }

void conf_handle_first_join ( struct confbridge_conference conference  ) 

Callback to execute any time we transition from zero to one active users.

Parameters:
conference The conference bridge with a single active user joined
Return values:
0 success
-1 failure

Definition at line 1178 of file app_confbridge.c.

References AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), and confbridge_conference::name.

Referenced by join_marked(), join_unmarked(), and join_waitmarked().

01179 {
01180    ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "confbridge:%s", conference->name);
01181 }

int conf_handle_inactive_waitmarked ( struct confbridge_user user  ) 

Handle actions every time a waitmarked user joins w/o a marked user present.

Parameters:
user The waitmarked user
Return values:
0 success
-1 failure

Definition at line 1142 of file app_confbridge.c.

References ast_test_flag, confbridge_user::b_profile, conf_get_sound(), CONF_SOUND_WAIT_FOR_LEADER, play_prompt_to_user(), bridge_profile::sounds, confbridge_user::u_profile, and USER_OPT_QUIET.

Referenced by conf_default_join_waitmarked().

01143 {
01144    /* If we have not been quieted play back that they are waiting for the leader */
01145    if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET) && play_prompt_to_user(user,
01146          conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, user->b_profile.sounds))) {
01147       /* user hungup while the sound was playing */
01148       return -1;
01149    }
01150    return 0;
01151 }

int conf_handle_only_unmarked ( struct confbridge_user user  ) 

Handle actions whenever an unmarked user joins an inactive conference.

Note:
These actions seem like they could apply just as well to a marked user and possibly be made to happen any time transitioning to a single state.
Parameters:
user The unmarked user

Definition at line 1153 of file app_confbridge.c.

References ast_test_flag, confbridge_user::b_profile, conf_get_sound(), CONF_SOUND_ONLY_PERSON, play_prompt_to_user(), bridge_profile::sounds, confbridge_user::u_profile, USER_OPT_NOONLYPERSON, and USER_OPT_QUIET.

Referenced by join_unmarked().

01154 {
01155    /* If audio prompts have not been quieted or this prompt quieted play it on out */
01156    if (!ast_test_flag(&user->u_profile, USER_OPT_QUIET | USER_OPT_NOONLYPERSON)) {
01157       if (play_prompt_to_user(user,
01158          conf_get_sound(CONF_SOUND_ONLY_PERSON, user->b_profile.sounds))) {
01159          /* user hungup while the sound was playing */
01160          return -1;
01161       }
01162    }
01163    return 0;
01164 }

void conf_handle_second_active ( struct confbridge_conference conference  ) 

Handle when a conference moves to having more than one active participant.

Parameters:
conference The conference bridge with more than one active participant

Definition at line 1183 of file app_confbridge.c.

References confbridge_conference::active_list, AST_LIST_FIRST, ast_test_flag, conf_moh_stop(), conf_update_user_mute(), confbridge_user::u_profile, and USER_OPT_MUSICONHOLD.

Referenced by join_active(), join_marked(), and join_unmarked().

01184 {
01185    /* If we are the second participant we may need to stop music on hold on the first */
01186    struct confbridge_user *first_user = AST_LIST_FIRST(&conference->active_list);
01187 
01188    if (ast_test_flag(&first_user->u_profile, USER_OPT_MUSICONHOLD)) {
01189       conf_moh_stop(first_user);
01190    }
01191    conf_update_user_mute(first_user);
01192 }

static int conf_handle_talker_cb ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt,
int  talking 
) [static]

Definition at line 1487 of file app_confbridge.c.

References ao2_cleanup, ao2_find, ast_json_pack(), ast_json_unref(), ast_test_flag, ast_bridge_channel::chan, confbridge_talking_type(), confbridge_user::conference, confbridge_conference::name, NULL, OBJ_KEY, RAII_VAR, send_conf_stasis(), confbridge_user::u_profile, and USER_OPT_ADMIN.

Referenced by confbridge_exec().

01488 {
01489    const struct confbridge_user *user = hook_pvt;
01490    RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
01491    struct ast_json *talking_extras;
01492 
01493    conference = ao2_find(conference_bridges, user->conference->name, OBJ_KEY);
01494    if (!conference) {
01495       /* Remove the hook since the conference does not exist. */
01496       return -1;
01497    }
01498 
01499    talking_extras = ast_json_pack("{s: s, s: b}",
01500       "talking_status", talking ? "on" : "off",
01501       "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN));
01502    if (!talking_extras) {
01503       return 0;
01504    }
01505 
01506    send_conf_stasis(conference, bridge_channel->chan, confbridge_talking_type(), talking_extras, 0);
01507    ast_json_unref(talking_extras);
01508    return 0;
01509 }

static int conf_is_recording ( struct confbridge_conference conference  )  [static]

Definition at line 617 of file app_confbridge.c.

References NULL, and confbridge_conference::record_chan.

Referenced by action_confbridgestartrecord(), conf_start_record(), conf_stop_record(), and handle_cli_confbridge_start_record().

00618 {
00619    return conference->record_chan != NULL;
00620 }

void conf_moh_start ( struct confbridge_user user  ) 

Start MOH for the conference user.

Parameters:
user Conference user to start MOH on.
Returns:
Nothing

Definition at line 1081 of file app_confbridge.c.

References ast_bridge_lock, ast_bridge_suspend(), ast_bridge_unlock, ast_bridge_unsuspend(), ast_moh_start(), confbridge_conference::bridge, confbridge_user::chan, confbridge_user::conference, user_profile::moh_class, NULL, confbridge_user::playing_moh, confbridge_user::suspended_moh, and confbridge_user::u_profile.

Referenced by conf_mute_moh_inactive_waitmarked(), conf_mute_only_active(), and leave_marked().

01082 {
01083    user->playing_moh = 1;
01084    if (!user->suspended_moh) {
01085       int in_bridge;
01086 
01087       /*
01088        * Locking the ast_bridge here is the only way to hold off the
01089        * call to ast_bridge_join() in confbridge_exec() from
01090        * interfering with the bridge and MOH operations here.
01091        */
01092       ast_bridge_lock(user->conference->bridge);
01093 
01094       /*
01095        * Temporarily suspend the user from the bridge so we have
01096        * control to start MOH if needed.
01097        */
01098       in_bridge = !ast_bridge_suspend(user->conference->bridge, user->chan);
01099       ast_moh_start(user->chan, user->u_profile.moh_class, NULL);
01100       if (in_bridge) {
01101          ast_bridge_unsuspend(user->conference->bridge, user->chan);
01102       }
01103 
01104       ast_bridge_unlock(user->conference->bridge);
01105    }
01106 }

void conf_moh_stop ( struct confbridge_user user  ) 

Stop MOH for the conference user.

Parameters:
user Conference user to stop MOH on.
Returns:
Nothing

Definition at line 1054 of file app_confbridge.c.

References ast_bridge_lock, ast_bridge_suspend(), ast_bridge_unlock, ast_bridge_unsuspend(), ast_moh_stop(), confbridge_conference::bridge, confbridge_user::chan, confbridge_user::conference, confbridge_user::playing_moh, and confbridge_user::suspended_moh.

Referenced by conf_default_leave_waitmarked(), conf_handle_second_active(), leave_marked(), leave_unmarked(), and transition_to_marked().

01055 {
01056    user->playing_moh = 0;
01057    if (!user->suspended_moh) {
01058       int in_bridge;
01059 
01060       /*
01061        * Locking the ast_bridge here is the only way to hold off the
01062        * call to ast_bridge_join() in confbridge_exec() from
01063        * interfering with the bridge and MOH operations here.
01064        */
01065       ast_bridge_lock(user->conference->bridge);
01066 
01067       /*
01068        * Temporarily suspend the user from the bridge so we have
01069        * control to stop MOH if needed.
01070        */
01071       in_bridge = !ast_bridge_suspend(user->conference->bridge, user->chan);
01072       ast_moh_stop(user->chan);
01073       if (in_bridge) {
01074          ast_bridge_unsuspend(user->conference->bridge, user->chan);
01075       }
01076 
01077       ast_bridge_unlock(user->conference->bridge);
01078    }
01079 }

static void conf_moh_suspend ( struct confbridge_user user  )  [static]

Definition at line 1133 of file app_confbridge.c.

References ao2_lock, ao2_unlock, ast_moh_stop(), confbridge_user::chan, confbridge_user::conference, confbridge_user::playing_moh, and confbridge_user::suspended_moh.

Referenced by conf_handle_dtmf().

01134 {
01135    ao2_lock(user->conference);
01136    if (user->suspended_moh++ == 0 && user->playing_moh) {
01137       ast_moh_stop(user->chan);
01138    }
01139    ao2_unlock(user->conference);
01140 }

static void conf_moh_unsuspend ( struct confbridge_user user  )  [static]

void conf_mute_only_active ( struct confbridge_conference conference  ) 

Attempt to mute/play MOH to the only user in the conference if they require it.

Parameters:
conference A conference bridge containing a single user

Definition at line 3269 of file app_confbridge.c.

References confbridge_conference::active_list, AST_LIST_FIRST, ast_test_flag, conf_moh_start(), conf_update_user_mute(), confbridge_user::u_profile, and USER_OPT_MUSICONHOLD.

Referenced by transition_to_single(), and transition_to_single_marked().

03270 {
03271    struct confbridge_user *only_user = AST_LIST_FIRST(&conference->active_list);
03272 
03273    /* Turn on MOH if the single participant is set up for it */
03274    if (ast_test_flag(&only_user->u_profile, USER_OPT_MUSICONHOLD)) {
03275       conf_moh_start(only_user);
03276    }
03277    conf_update_user_mute(only_user);
03278 }

static int conf_rec_name ( struct confbridge_user user,
const char *  conf_name 
) [static]

Definition at line 1548 of file app_confbridge.c.

References ast_channel_uniqueid(), ast_config_AST_SPOOL_DIR, ast_dsp_get_threshold_from_settings(), ast_log, ast_mkdir(), ast_play_and_record(), ast_record_review(), ast_test_flag, confbridge_user::chan, errno, LOG_WARNING, confbridge_user::name_rec_location, NULL, THRESHOLD_SILENCE, confbridge_user::u_profile, and USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW.

Referenced by confbridge_exec().

01549 {
01550    char destdir[PATH_MAX];
01551    int res;
01552    int duration = 20;
01553 
01554    snprintf(destdir, sizeof(destdir), "%s/confbridge", ast_config_AST_SPOOL_DIR);
01555 
01556    if (ast_mkdir(destdir, 0777) != 0) {
01557       ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno));
01558       return -1;
01559    }
01560    snprintf(user->name_rec_location, sizeof(user->name_rec_location),
01561        "%s/confbridge-name-%s-%s", destdir,
01562        conf_name, ast_channel_uniqueid(user->chan));
01563 
01564    if (!(ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW))) {
01565       res = ast_play_and_record(user->chan,
01566          "vm-rec-name",
01567          user->name_rec_location,
01568          10,
01569          "sln",
01570          &duration,
01571          NULL,
01572          ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE),
01573          0,
01574          NULL);
01575    } else {
01576       res = ast_record_review(user->chan,
01577          "vm-rec-name",
01578          user->name_rec_location,
01579          10,
01580          "sln",
01581          &duration,
01582          NULL);
01583    }
01584 
01585    if (res == -1) {
01586       user->name_rec_location[0] = '\0';
01587       return -1;
01588    }
01589    return 0;
01590 }

void conf_remove_user_active ( struct confbridge_conference conference,
struct confbridge_user user 
)

Remove a conference bridge user from the unmarked active conference users in the conference.

Parameters:
conference The conference bridge to remove the user from
user The conference bridge user to remove from the conference

Definition at line 3256 of file app_confbridge.c.

References confbridge_conference::active_list, confbridge_conference::activeusers, AST_LIST_REMOVE, and confbridge_user::list.

Referenced by leave_active(), and leave_unmarked().

03257 {
03258    AST_LIST_REMOVE(&conference->active_list, user, list);
03259    conference->activeusers--;
03260 }

void conf_remove_user_marked ( struct confbridge_conference conference,
struct confbridge_user user 
)

Remove a conference bridge user from the marked active conference users in the conference.

Parameters:
conference The conference bridge to remove the user from
user The conference bridge user to remove from the conference

Definition at line 3262 of file app_confbridge.c.

References confbridge_conference::active_list, confbridge_conference::activeusers, AST_LIST_REMOVE, confbridge_user::list, and confbridge_conference::markedusers.

Referenced by leave_marked().

03263 {
03264    AST_LIST_REMOVE(&conference->active_list, user, list);
03265    conference->activeusers--;
03266    conference->markedusers--;
03267 }

void conf_remove_user_waiting ( struct confbridge_conference conference,
struct confbridge_user user 
)

Remove a conference bridge user from the waiting conference users in the conference.

Parameters:
conference The conference bridge to remove the user from
user The conference bridge user to remove from the conference

Definition at line 3280 of file app_confbridge.c.

References AST_LIST_REMOVE, confbridge_user::list, confbridge_conference::waiting_list, and confbridge_conference::waitingusers.

Referenced by conf_default_leave_waitmarked().

03281 {
03282    AST_LIST_REMOVE(&conference->waiting_list, user, list);
03283    conference->waitingusers--;
03284 }

static int conf_start_record ( struct confbridge_conference conference  )  [static]

Definition at line 665 of file app_confbridge.c.

References ao2_ref, ast_answer(), AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE, ast_bridge_features_destroy(), ast_bridge_features_new(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_channel_ref, ast_channel_unref, ast_format_cap_alloc, ast_format_cap_append, AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_slin, ast_hangup(), ast_log, ast_request(), ast_set_flag, ast_str_buffer(), ast_test_suite_event_notify, confbridge_conference::b_profile, confbridge_conference::bridge, conf_is_recording(), ast_bridge_features::feature_flags, is_new_rec_file(), LOG_WARNING, bridge_profile::name, confbridge_conference::name, NULL, confbridge_conference::orig_rec_file, pbx_exec(), pbx_findapp(), bridge_profile::rec_file, confbridge_conference::record_chan, confbridge_conference::record_filename, send_start_record_event(), and set_rec_filename().

Referenced by action_confbridgestartrecord(), handle_cli_confbridge_start_record(), and join_conference_bridge().

00666 {
00667    struct ast_app *mixmonapp;
00668    struct ast_channel *chan;
00669    struct ast_format_cap *cap;
00670    struct ast_bridge_features *features;
00671 
00672    if (conf_is_recording(conference)) {
00673       return -1;
00674    }
00675 
00676    mixmonapp = pbx_findapp("MixMonitor");
00677    if (!mixmonapp) {
00678       ast_log(LOG_WARNING, "Cannot record ConfBridge, MixMonitor app is not installed\n");
00679       return -1;
00680    }
00681 
00682    features = ast_bridge_features_new();
00683    if (!features) {
00684       return -1;
00685    }
00686    ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
00687 
00688    cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
00689    if (!cap) {
00690       ast_bridge_features_destroy(features);
00691       return -1;
00692    }
00693    ast_format_cap_append(cap, ast_format_slin, 0);
00694 
00695    /* Create the recording channel. */
00696    chan = ast_request("CBRec", cap, NULL, NULL, conference->name, NULL);
00697    ao2_ref(cap, -1);
00698    if (!chan) {
00699       ast_bridge_features_destroy(features);
00700       return -1;
00701    }
00702 
00703    /* Start recording. */
00704    set_rec_filename(conference, &conference->record_filename,
00705       is_new_rec_file(conference->b_profile.rec_file, &conference->orig_rec_file));
00706    ast_answer(chan);
00707    pbx_exec(chan, mixmonapp, ast_str_buffer(conference->record_filename));
00708 
00709    /* Put the channel into the conference bridge. */
00710    ast_channel_ref(chan);
00711    conference->record_chan = chan;
00712    if (ast_bridge_impart(conference->bridge, chan, NULL, features,
00713       AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
00714       ast_hangup(chan);
00715       ast_channel_unref(chan);
00716       conference->record_chan = NULL;
00717       return -1;
00718    }
00719 
00720    ast_test_suite_event_notify("CONF_START_RECORD", "Message: started conference recording channel\r\nConference: %s", conference->b_profile.name);
00721    send_start_record_event(conference);
00722 
00723    return 0;
00724 }

static int conf_stop_record ( struct confbridge_conference conference  )  [static]

Definition at line 633 of file app_confbridge.c.

References ast_channel_unref, AST_CONTROL_HANGUP, AST_FRAME_CONTROL, ast_queue_frame(), ast_test_suite_event_notify, confbridge_conference::b_profile, conf_is_recording(), bridge_profile::name, NULL, confbridge_conference::record_chan, and send_stop_record_event().

Referenced by action_confbridgestoprecord(), conf_ended(), and handle_cli_confbridge_stop_record().

00634 {
00635    struct ast_channel *chan;
00636    struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
00637 
00638    if (!conf_is_recording(conference)) {
00639       return -1;
00640    }
00641 
00642    /* Remove the recording channel from the conference bridge. */
00643    chan = conference->record_chan;
00644    conference->record_chan = NULL;
00645    ast_queue_frame(chan, &f);
00646    ast_channel_unref(chan);
00647 
00648    ast_test_suite_event_notify("CONF_STOP_RECORD", "Message: stopped conference recording channel\r\nConference: %s", conference->b_profile.name);
00649    send_stop_record_event(conference);
00650 
00651    return 0;
00652 }

void conf_update_user_mute ( struct confbridge_user user  ) 

Update the actual mute status of the user and set it on the bridge.

Parameters:
user User to update the mute status.
Returns:
Nothing

Definition at line 1021 of file app_confbridge.c.

References ast_channel_name(), ast_debug, ast_test_flag, ast_test_suite_event_notify, confbridge_user::b_profile, confbridge_user::chan, confbridge_user::conference, confbridge_user::features, confbridge_conference::markedusers, ast_bridge_features::mute, confbridge_user::muted, bridge_profile::name, confbridge_user::playing_moh, confbridge_user::u_profile, and USER_OPT_WAITMARKED.

Referenced by action_toggle_mute(), action_toggle_mute_participants(), conf_handle_second_active(), conf_mute_moh_inactive_waitmarked(), conf_mute_only_active(), generic_mute_unmute_user(), join_active(), join_marked(), join_unmarked(), leave_marked(), and transition_to_marked().

01022 {
01023    int mute_user;
01024    int mute_system;
01025    int mute_effective;
01026 
01027    /* User level mute request. */
01028    mute_user = user->muted;
01029 
01030    /* System level mute request. */
01031    mute_system = user->playing_moh
01032       /*
01033        * Do not allow waitmarked users to talk to anyone unless there
01034        * is a marked user present.
01035        */
01036       || (!user->conference->markedusers
01037          && ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED));
01038 
01039    mute_effective = mute_user || mute_system;
01040 
01041    ast_debug(1, "User %s is %s: user:%d system:%d.\n",
01042       ast_channel_name(user->chan), mute_effective ? "muted" : "unmuted",
01043       mute_user, mute_system);
01044    user->features.mute = mute_effective;
01045    ast_test_suite_event_notify("CONF_MUTE_UPDATE",
01046       "Mode: %s\r\n"
01047       "Conference: %s\r\n"
01048       "Channel: %s",
01049       mute_effective ? "muted" : "unmuted",
01050       user->b_profile.name,
01051       ast_channel_name(user->chan));
01052 }

static int confbridge_exec ( struct ast_channel chan,
const char *  data 
) [static]

The ConfBridge application.

Definition at line 1593 of file app_confbridge.c.

References args, ast_answer(), AST_APP_ARG, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, ast_audiohook_volume_get(), ast_audiohook_volume_set(), ast_autoservice_start(), ast_autoservice_stop(), ast_bridge_features_cleanup(), ast_bridge_features_init(), AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_bridge_join(), ast_bridge_talk_detector_hook(), ast_check_hangup(), AST_DECLARE_APP_ARGS, ast_filedelete(), ast_free, ast_func_write(), ast_log, ast_module_helper(), ast_shutting_down(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_stream_and_wait(), ast_strlen_zero, ast_test_flag, confbridge_user::b_profile, confbridge_conference::bridge, confbridge_user::chan, conf_bridge_profile_destroy(), conf_find_bridge_profile(), conf_find_user_profile(), conf_get_pin(), conf_get_sound(), conf_handle_talker_cb(), conf_moh_unsuspend(), conf_rec_name(), conf_set_menu_to_user(), CONF_SOUND_HAS_JOINED, CONF_SOUND_HAS_LEFT, CONF_SOUND_JOIN, CONF_SOUND_KICKED, CONF_SOUND_LEAVE, DEFAULT_BRIDGE_PROFILE, DEFAULT_MENU_PROFILE, DEFAULT_SILENCE_THRESHOLD, DEFAULT_TALKING_THRESHOLD, DEFAULT_USER_PROFILE, ast_bridge_tech_optimizations::drop_silence, ast_bridge_features::dtmf_passthrough, confbridge_user::features, handle_video_on_exit(), handle_video_on_join(), join_conference_bridge(), confbridge_user::kicked, leave_conference(), LOG_WARNING, MAX_CONF_NAME, confbridge_user::muted, confbridge_user::name_rec_location, NULL, parse(), pbx_builtin_setvar_helper(), user_profile::pin, play_sound_file(), quiet, send_join_event(), send_leave_event(), ast_bridge_tech_optimizations::silence_threshold, user_profile::silence_threshold, bridge_profile::sounds, ast_bridge_tech_optimizations::talking_threshold, user_profile::talking_threshold, confbridge_user::tech_args, confbridge_user::u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW, USER_OPT_DENOISE, USER_OPT_DROP_SILENCE, USER_OPT_DTMF_PASS, USER_OPT_JITTERBUFFER, USER_OPT_MARKEDUSER, USER_OPT_QUIET, USER_OPT_STARTMUTED, and USER_OPT_TALKER_DETECT.

Referenced by load_module().

01594 {
01595    int res = 0, volume_adjustments[2];
01596    int quiet = 0;
01597    char *parse;
01598    const char *b_profile_name = NULL;
01599    const char *u_profile_name = NULL;
01600    const char *menu_profile_name = NULL;
01601    struct confbridge_conference *conference = NULL;
01602    struct confbridge_user user = {
01603       .chan = chan,
01604       .tech_args.talking_threshold = DEFAULT_TALKING_THRESHOLD,
01605       .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD,
01606       .tech_args.drop_silence = 0,
01607    };
01608    AST_DECLARE_APP_ARGS(args,
01609       AST_APP_ARG(conf_name);
01610       AST_APP_ARG(b_profile_name);
01611       AST_APP_ARG(u_profile_name);
01612       AST_APP_ARG(menu_profile_name);
01613    );
01614 
01615    if (ast_channel_state(chan) != AST_STATE_UP) {
01616       ast_answer(chan);
01617    }
01618 
01619    if (ast_bridge_features_init(&user.features)) {
01620       pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
01621       res = -1;
01622       goto confbridge_cleanup;
01623    }
01624 
01625    /* We need to make a copy of the input string if we are going to modify it! */
01626    parse = ast_strdupa(data);
01627 
01628    AST_STANDARD_APP_ARGS(args, parse);
01629 
01630    if (ast_strlen_zero(args.conf_name)) {
01631       pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
01632       ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app);
01633       res = -1;
01634       goto confbridge_cleanup;
01635    }
01636 
01637    if (strlen(args.conf_name) >= MAX_CONF_NAME) {
01638       pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
01639       ast_log(LOG_WARNING, "%s does not accept conference names longer than %d\n", app, MAX_CONF_NAME - 1);
01640       res = -1;
01641       goto confbridge_cleanup;
01642    }
01643 
01644    /* bridge profile name */
01645    if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) {
01646       b_profile_name = args.b_profile_name;
01647    }
01648    if (!conf_find_bridge_profile(chan, b_profile_name, &user.b_profile)) {
01649       pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
01650       ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name ?
01651          b_profile_name : DEFAULT_BRIDGE_PROFILE);
01652       res = -1;
01653       goto confbridge_cleanup;
01654    }
01655 
01656    /* user profile name */
01657    if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) {
01658       u_profile_name = args.u_profile_name;
01659    }
01660    if (!conf_find_user_profile(chan, u_profile_name, &user.u_profile)) {
01661       pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
01662       ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name ?
01663          u_profile_name : DEFAULT_USER_PROFILE);
01664       res = -1;
01665       goto confbridge_cleanup;
01666    }
01667 
01668    quiet = ast_test_flag(&user.u_profile, USER_OPT_QUIET);
01669 
01670    /* ask for a PIN immediately after finding user profile.  This has to be
01671     * prompted for requardless of quiet setting. */
01672    if (!ast_strlen_zero(user.u_profile.pin)) {
01673       if (conf_get_pin(chan, &user)) {
01674          pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
01675          res = -1; /* invalid PIN */
01676          goto confbridge_cleanup;
01677       }
01678    }
01679 
01680    /* See if we need them to record a intro name */
01681    if (!quiet &&
01682       (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE) ||
01683       (ast_test_flag(&user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW)))) {
01684       conf_rec_name(&user, args.conf_name);
01685    }
01686 
01687    /* menu name */
01688    if (args.argc > 3 && !ast_strlen_zero(args.menu_profile_name)) {
01689       menu_profile_name = args.menu_profile_name;
01690    }
01691 
01692    if (conf_set_menu_to_user(chan, &user, menu_profile_name)) {
01693       pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
01694       ast_log(LOG_WARNING, "Conference menu profile %s does not exist\n", menu_profile_name ?
01695          menu_profile_name : DEFAULT_MENU_PROFILE);
01696       res = -1;
01697       goto confbridge_cleanup;
01698    }
01699 
01700    /* Set if DTMF should pass through for this user or not */
01701    if (ast_test_flag(&user.u_profile, USER_OPT_DTMF_PASS)) {
01702       user.features.dtmf_passthrough = 1;
01703    } else {
01704       user.features.dtmf_passthrough = 0;
01705    }
01706 
01707    /* Set dsp threshold values if present */
01708    if (user.u_profile.talking_threshold) {
01709       user.tech_args.talking_threshold = user.u_profile.talking_threshold;
01710    }
01711    if (user.u_profile.silence_threshold) {
01712       user.tech_args.silence_threshold = user.u_profile.silence_threshold;
01713    }
01714 
01715    /* Set a talker indicate call back if talking detection is requested */
01716    if (ast_test_flag(&user.u_profile, USER_OPT_TALKER_DETECT)) {
01717       if (ast_bridge_talk_detector_hook(&user.features, conf_handle_talker_cb,
01718          &user, NULL, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
01719          pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
01720          res = -1;
01721          goto confbridge_cleanup;
01722       }
01723    }
01724 
01725    /* If the caller should be joined already muted, set the flag before we join. */
01726    if (ast_test_flag(&user.u_profile, USER_OPT_STARTMUTED)) {
01727       /* Set user level mute request. */
01728       user.muted = 1;
01729    }
01730 
01731    /* Look for a conference bridge matching the provided name */
01732    if (!(conference = join_conference_bridge(args.conf_name, &user))) {
01733       pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "FAILED");
01734       res = -1;
01735       goto confbridge_cleanup;
01736    }
01737 
01738    /* Keep a copy of volume adjustments so we can restore them later if need be */
01739    volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ);
01740    volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE);
01741 
01742    if (ast_test_flag(&user.u_profile, USER_OPT_DROP_SILENCE)) {
01743       user.tech_args.drop_silence = 1;
01744    }
01745 
01746    if (ast_test_flag(&user.u_profile, USER_OPT_JITTERBUFFER)) {
01747       char *func_jb;
01748       if ((func_jb = ast_module_helper("", "func_jitterbuffer", 0, 0, 0, 0))) {
01749          ast_free(func_jb);
01750          ast_func_write(chan, "JITTERBUFFER(adaptive)", "default");
01751       }
01752    }
01753 
01754    if (ast_test_flag(&user.u_profile, USER_OPT_DENOISE)) {
01755       char *mod_speex;
01756       /* Reduce background noise from each participant */
01757       if ((mod_speex = ast_module_helper("", "codec_speex", 0, 0, 0, 0))) {
01758          ast_free(mod_speex);
01759          ast_func_write(chan, "DENOISE(rx)", "on");
01760       }
01761    }
01762 
01763    /* if this user has a intro, play it before entering */
01764    if (!ast_strlen_zero(user.name_rec_location)) {
01765       ast_autoservice_start(chan);
01766       play_sound_file(conference, user.name_rec_location);
01767       play_sound_file(conference,
01768          conf_get_sound(CONF_SOUND_HAS_JOINED, user.b_profile.sounds));
01769       ast_autoservice_stop(chan);
01770    }
01771 
01772    /* Play the Join sound to both the conference and the user entering. */
01773    if (!quiet) {
01774       const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, user.b_profile.sounds);
01775 
01776       ast_stream_and_wait(chan, join_sound, "");
01777       ast_autoservice_start(chan);
01778       play_sound_file(conference, join_sound);
01779       ast_autoservice_stop(chan);
01780    }
01781 
01782    /* See if we need to automatically set this user as a video source or not */
01783    handle_video_on_join(conference, user.chan, ast_test_flag(&user.u_profile, USER_OPT_MARKEDUSER));
01784 
01785    conf_moh_unsuspend(&user);
01786 
01787    /* Join our conference bridge for real */
01788    send_join_event(&user, conference);
01789    ast_bridge_join(conference->bridge,
01790       chan,
01791       NULL,
01792       &user.features,
01793       &user.tech_args,
01794       0);
01795 
01796    if (!user.kicked && ast_check_hangup(chan)) {
01797       pbx_builtin_setvar_helper(chan, "CONFBRIDGE_RESULT", "HANGUP");
01798    }
01799 
01800    send_leave_event(&user, conference);
01801 
01802    /* if we're shutting down, don't attempt to do further processing */
01803    if (ast_shutting_down()) {
01804       /*
01805        * Not taking any new calls at this time.  We cannot create
01806        * the announcer channel if this is the first channel into
01807        * the conference and we certainly cannot create any
01808        * recording channel.
01809        */
01810       leave_conference(&user);
01811       conference = NULL;
01812       goto confbridge_cleanup;
01813    }
01814 
01815    /* If this user was a video source, we need to clean up and possibly pick a new source. */
01816    handle_video_on_exit(conference, user.chan);
01817 
01818    /* if this user has a intro, play it when leaving */
01819    if (!quiet && !ast_strlen_zero(user.name_rec_location)) {
01820       ast_autoservice_start(chan);
01821       play_sound_file(conference, user.name_rec_location);
01822       play_sound_file(conference,
01823          conf_get_sound(CONF_SOUND_HAS_LEFT, user.b_profile.sounds));
01824       ast_autoservice_stop(chan);
01825    }
01826 
01827    /* play the leave sound */
01828    if (!quiet) {
01829       const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, user.b_profile.sounds);
01830       ast_autoservice_start(chan);
01831       play_sound_file(conference, leave_sound);
01832       ast_autoservice_stop(chan);
01833    }
01834 
01835    /* Easy as pie, depart this channel from the conference bridge */
01836    leave_conference(&user);
01837    conference = NULL;
01838 
01839    /* If the user was kicked from the conference play back the audio prompt for it */
01840    if (!quiet && user.kicked) {
01841       res = ast_stream_and_wait(chan,
01842          conf_get_sound(CONF_SOUND_KICKED, user.b_profile.sounds),
01843          "");
01844    }
01845 
01846    /* Restore volume adjustments to previous values in case they were changed */
01847    if (volume_adjustments[0]) {
01848       ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]);
01849    }
01850    if (volume_adjustments[1]) {
01851       ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]);
01852    }
01853 
01854    if (!ast_strlen_zero(user.name_rec_location)) {
01855       ast_filedelete(user.name_rec_location, NULL);
01856    }
01857 
01858 confbridge_cleanup:
01859    ast_bridge_features_cleanup(&user.features);
01860    conf_bridge_profile_destroy(&user.b_profile);
01861    return res;
01862 }

static int conference_bridge_cmp_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Comparison function used for conference bridges container.

Definition at line 369 of file app_confbridge.c.

References CMP_MATCH, confbridge_conference::name, OBJ_KEY, OBJ_PARTIAL_KEY, and OBJ_POINTER.

Referenced by load_module().

00370 {
00371    const struct confbridge_conference *left = obj;
00372    const struct confbridge_conference *right = arg;
00373    const char *right_name = arg;
00374    int cmp;
00375 
00376    switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
00377    default:
00378    case OBJ_POINTER:
00379       right_name = right->name;
00380       /* Fall through */
00381    case OBJ_KEY:
00382       cmp = strcasecmp(left->name, right_name);
00383       break;
00384    case OBJ_PARTIAL_KEY:
00385       cmp = strncasecmp(left->name, right_name, strlen(right_name));
00386       break;
00387    }
00388    return cmp ? 0 : CMP_MATCH;
00389 }

static int conference_bridge_hash_cb ( const void *  obj,
const int  flags 
) [static]

Hashing function used for conference bridges container.

Definition at line 345 of file app_confbridge.c.

References ast_assert, ast_str_case_hash(), confbridge_conference::name, name, OBJ_KEY, OBJ_PARTIAL_KEY, and OBJ_POINTER.

Referenced by load_module().

00346 {
00347    const struct confbridge_conference *conference = obj;
00348    const char *name = obj;
00349    int hash;
00350 
00351    switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
00352    default:
00353    case OBJ_POINTER:
00354       name = conference->name;
00355       /* Fall through */
00356    case OBJ_KEY:
00357       hash = ast_str_case_hash(name);
00358       break;
00359    case OBJ_PARTIAL_KEY:
00360       /* Should never happen in hash callback. */
00361       ast_assert(0);
00362       hash = 0;
00363       break;
00364    }
00365    return hash;
00366 }

static void destroy_conference_bridge ( void *  obj  )  [static]

Destroy a conference bridge.

Parameters:
obj The conference bridge object
Returns:
Returns nothing

Definition at line 934 of file app_confbridge.c.

References ast_bridge_destroy(), ast_channel_cleanup, ast_debug, ast_free, ast_hangup(), ast_mutex_destroy, confbridge_conference::b_profile, confbridge_conference::bridge, conf_announce_channel_depart(), conf_bridge_profile_destroy(), confbridge_conference::name, NULL, confbridge_conference::orig_rec_file, confbridge_conference::playback_chan, confbridge_conference::playback_lock, confbridge_conference::record_chan, and confbridge_conference::record_filename.

Referenced by join_conference_bridge().

00935 {
00936    struct confbridge_conference *conference = obj;
00937 
00938    ast_debug(1, "Destroying conference bridge '%s'\n", conference->name);
00939 
00940    if (conference->playback_chan) {
00941       conf_announce_channel_depart(conference->playback_chan);
00942       ast_hangup(conference->playback_chan);
00943       conference->playback_chan = NULL;
00944    }
00945 
00946    /* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */
00947    if (conference->bridge) {
00948       ast_bridge_destroy(conference->bridge, 0);
00949       conference->bridge = NULL;
00950    }
00951 
00952    ast_channel_cleanup(conference->record_chan);
00953    ast_free(conference->orig_rec_file);
00954    ast_free(conference->record_filename);
00955 
00956    conf_bridge_profile_destroy(&conference->b_profile);
00957    ast_mutex_destroy(&conference->playback_lock);
00958 }

static int execute_menu_entry ( struct confbridge_conference conference,
struct confbridge_user user,
struct ast_bridge_channel bridge_channel,
struct conf_menu_entry menu_entry,
struct conf_menu menu 
) [static]

Definition at line 2090 of file app_confbridge.c.

References conf_menu_action::action, action_dialplan_exec(), action_kick_last(), action_playback(), action_playback_and_continue(), action_toggle_mute(), action_toggle_mute_participants(), conf_menu_entry::actions, announce_user_count(), ao2_lock, ao2_unlock, AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_DIRECTION_WRITE, ast_audiohook_volume_adjust(), ast_audiohook_volume_set(), ast_bridge_remove(), ast_bridge_set_single_src_video_mode(), ast_channel_name(), AST_LIST_TRAVERSE, ast_test_flag, ast_test_suite_event_notify, confbridge_user::b_profile, confbridge_conference::bridge, confbridge_user::chan, ast_bridge_channel::chan, conf_get_sound(), CONF_SOUND_LOCKED_NOW, CONF_SOUND_UNLOCKED_NOW, conf_menu_action::data, conf_menu_entry::dtmf, handle_video_on_exit(), conf_menu_action::id, confbridge_conference::locked, MENU_ACTION_ADMIN_KICK_LAST, MENU_ACTION_ADMIN_TOGGLE_LOCK, MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS, MENU_ACTION_DECREASE_LISTENING, MENU_ACTION_DECREASE_TALKING, MENU_ACTION_DIALPLAN_EXEC, MENU_ACTION_INCREASE_LISTENING, MENU_ACTION_INCREASE_TALKING, MENU_ACTION_LEAVE, MENU_ACTION_NOOP, MENU_ACTION_PARTICIPANT_COUNT, MENU_ACTION_PLAYBACK, MENU_ACTION_PLAYBACK_AND_CONTINUE, MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC, MENU_ACTION_RESET_LISTENING, MENU_ACTION_RESET_TALKING, MENU_ACTION_SET_SINGLE_VIDEO_SRC, MENU_ACTION_TOGGLE_MUTE, NULL, pbx_builtin_setvar_helper(), play_file(), conf_menu_action::playback_file, bridge_profile::sounds, confbridge_user::u_profile, and USER_OPT_ADMIN.

Referenced by action_playback_and_continue(), and conf_handle_dtmf().

02095 {
02096    struct conf_menu_action *menu_action;
02097    int isadmin = ast_test_flag(&user->u_profile, USER_OPT_ADMIN);
02098    int stop_prompts = 0;
02099    int res = 0;
02100 
02101    AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) {
02102       switch (menu_action->id) {
02103       case MENU_ACTION_TOGGLE_MUTE:
02104          res |= action_toggle_mute(conference, user, bridge_channel);
02105          break;
02106       case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
02107          if (!isadmin) {
02108             break;
02109          }
02110          action_toggle_mute_participants(conference, user);
02111          break;
02112       case MENU_ACTION_PARTICIPANT_COUNT:
02113          announce_user_count(conference, user, bridge_channel);
02114          break;
02115       case MENU_ACTION_PLAYBACK:
02116          if (!stop_prompts) {
02117             res |= action_playback(bridge_channel, menu_action->data.playback_file);
02118             ast_test_suite_event_notify("CONF_MENU_PLAYBACK",
02119                "Message: %s\r\nChannel: %s",
02120                menu_action->data.playback_file, ast_channel_name(bridge_channel->chan));
02121          }
02122          break;
02123       case MENU_ACTION_RESET_LISTENING:
02124          ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0);
02125          break;
02126       case MENU_ACTION_RESET_TALKING:
02127          ast_audiohook_volume_set(user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0);
02128          break;
02129       case MENU_ACTION_INCREASE_LISTENING:
02130          ast_audiohook_volume_adjust(user->chan,
02131             AST_AUDIOHOOK_DIRECTION_WRITE, 1);
02132          break;
02133       case MENU_ACTION_DECREASE_LISTENING:
02134          ast_audiohook_volume_adjust(user->chan,
02135             AST_AUDIOHOOK_DIRECTION_WRITE, -1);
02136          break;
02137       case MENU_ACTION_INCREASE_TALKING:
02138          ast_audiohook_volume_adjust(user->chan,
02139             AST_AUDIOHOOK_DIRECTION_READ, 1);
02140          break;
02141       case MENU_ACTION_DECREASE_TALKING:
02142          ast_audiohook_volume_adjust(user->chan,
02143             AST_AUDIOHOOK_DIRECTION_READ, -1);
02144          break;
02145       case MENU_ACTION_PLAYBACK_AND_CONTINUE:
02146          if (!(stop_prompts)) {
02147             res |= action_playback_and_continue(conference,
02148                user,
02149                bridge_channel,
02150                menu,
02151                menu_action->data.playback_file,
02152                menu_entry->dtmf,
02153                &stop_prompts);
02154          }
02155          break;
02156       case MENU_ACTION_DIALPLAN_EXEC:
02157          res |= action_dialplan_exec(bridge_channel, menu_action);
02158          break;
02159       case MENU_ACTION_ADMIN_TOGGLE_LOCK:
02160          if (!isadmin) {
02161             break;
02162          }
02163          conference->locked = (!conference->locked ? 1 : 0);
02164          res |= play_file(bridge_channel, NULL,
02165             (conference->locked ?
02166             conf_get_sound(CONF_SOUND_LOCKED_NOW, user->b_profile.sounds) :
02167             conf_get_sound(CONF_SOUND_UNLOCKED_NOW, user->b_profile.sounds))) < 0;
02168          break;
02169       case MENU_ACTION_ADMIN_KICK_LAST:
02170          res |= action_kick_last(conference, bridge_channel, user);
02171          break;
02172       case MENU_ACTION_LEAVE:
02173          pbx_builtin_setvar_helper(bridge_channel->chan, "CONFBRIDGE_RESULT", "DTMF");
02174          ao2_lock(conference);
02175          ast_bridge_remove(conference->bridge, bridge_channel->chan);
02176          ast_test_suite_event_notify("CONF_MENU_LEAVE",
02177             "Channel: %s",
02178             ast_channel_name(bridge_channel->chan));
02179          ao2_unlock(conference);
02180          break;
02181       case MENU_ACTION_NOOP:
02182          break;
02183       case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
02184          ao2_lock(conference);
02185          ast_bridge_set_single_src_video_mode(conference->bridge, bridge_channel->chan);
02186          ao2_unlock(conference);
02187          break;
02188       case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
02189          handle_video_on_exit(conference, bridge_channel->chan);
02190          break;
02191       }
02192    }
02193    return res;
02194 }

static int func_confbridge_info ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 3178 of file app_confbridge.c.

References confbridge_conference::active_list, ao2_find, ao2_lock, ao2_ref, ao2_unlock, args, AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_LIST_TRAVERSE, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, ast_test_flag, confbridge_user::list, confbridge_conference::locked, LOG_ERROR, OBJ_KEY, parse(), type, confbridge_user::u_profile, USER_OPT_ADMIN, USER_OPT_MARKEDUSER, and confbridge_conference::waiting_list.

03179 {
03180    char *parse;
03181    struct confbridge_conference *conference;
03182    struct confbridge_user *user;
03183    int count = 0;
03184    AST_DECLARE_APP_ARGS(args,
03185       AST_APP_ARG(type);
03186       AST_APP_ARG(confno);
03187    );
03188 
03189    /* parse all the required arguments and make sure they exist. */
03190    if (ast_strlen_zero(data)) {
03191       return -1;
03192    }
03193    parse = ast_strdupa(data);
03194    AST_STANDARD_APP_ARGS(args, parse);
03195    if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) {
03196       return -1;
03197    }
03198    conference = ao2_find(conference_bridges, args.confno, OBJ_KEY);
03199    if (!conference) {
03200       snprintf(buf, len, "0");
03201       return 0;
03202    }
03203 
03204    /* get the correct count for the type requested */
03205    ao2_lock(conference);
03206    if (!strncasecmp(args.type, "parties", 7)) {
03207       AST_LIST_TRAVERSE(&conference->active_list, user, list) {
03208          count++;
03209       }
03210       AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
03211          count++;
03212       }
03213    } else if (!strncasecmp(args.type, "admins", 6)) {
03214       AST_LIST_TRAVERSE(&conference->active_list, user, list) {
03215          if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
03216             count++;
03217          }
03218       }
03219    } else if (!strncasecmp(args.type, "marked", 6)) {
03220       AST_LIST_TRAVERSE(&conference->active_list, user, list) {
03221          if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
03222             count++;
03223          }
03224       }
03225    } else if (!strncasecmp(args.type, "locked", 6)) {
03226       count = conference->locked;
03227    } else {
03228       ast_log(LOG_ERROR, "Invalid keyword '%s' passed to CONFBRIDGE_INFO.  Should be one of: "
03229          "parties, admins, marked, or locked.\n", args.type);
03230    }
03231    snprintf(buf, len, "%d", count);
03232    ao2_unlock(conference);
03233    ao2_ref(conference, -1);
03234    return 0;
03235 }

static int generic_lock_unlock_helper ( int  lock,
const char *  conference_name 
) [static]

Definition at line 2478 of file app_confbridge.c.

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_test_suite_event_notify, confbridge_conference::b_profile, confbridge_conference::locked, bridge_profile::name, and OBJ_KEY.

Referenced by action_lock_unlock_helper(), handle_cli_confbridge_lock(), and handle_cli_confbridge_unlock().

02479 {
02480    struct confbridge_conference *conference;
02481    int res = 0;
02482 
02483    conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
02484    if (!conference) {
02485       return -1;
02486    }
02487    ao2_lock(conference);
02488    conference->locked = lock;
02489    ast_test_suite_event_notify("CONF_LOCK", "Message: conference %s\r\nConference: %s", conference->locked ? "locked" : "unlocked", conference->b_profile.name);
02490    ao2_unlock(conference);
02491    ao2_ref(conference, -1);
02492 
02493    return res;
02494 }

static int generic_mute_unmute_helper ( int  mute,
const char *  conference_name,
const char *  chan_name 
) [static]

Definition at line 2527 of file app_confbridge.c.

References confbridge_conference::active_list, ao2_cleanup, ao2_find, ast_channel_name(), AST_LIST_TRAVERSE, ast_test_flag, confbridge_user::chan, confbridge_user::conference, generic_mute_unmute_user(), confbridge_user::list, match(), NULL, OBJ_KEY, RAII_VAR, SCOPED_AO2LOCK, confbridge_user::u_profile, USER_OPT_ADMIN, and confbridge_conference::waiting_list.

Referenced by action_mute_unmute_helper(), and cli_mute_unmute_helper().

02529 {
02530    RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
02531    struct confbridge_user *user;
02532    int all = !strcasecmp("all", chan_name);
02533    int participants = !strcasecmp("participants", chan_name);
02534    int res = -2;
02535 
02536    conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
02537    if (!conference) {
02538       return -1;
02539    }
02540 
02541    {
02542       SCOPED_AO2LOCK(bridge_lock, conference);
02543       AST_LIST_TRAVERSE(&conference->active_list, user, list) {
02544          int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
02545             strlen(chan_name));
02546          if (match || all
02547             || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
02548             generic_mute_unmute_user(conference, user, mute);
02549             res = 0;
02550             if (match) {
02551                return res;
02552             }
02553          }
02554       }
02555 
02556       AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
02557          int match = !strncasecmp(chan_name, ast_channel_name(user->chan),
02558             strlen(chan_name));
02559          if (match || all
02560             || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
02561             generic_mute_unmute_user(conference, user, mute);
02562             res = 0;
02563             if (match) {
02564                return res;
02565             }
02566          }
02567       }
02568    }
02569 
02570    return res;
02571 }

static void generic_mute_unmute_user ( struct confbridge_conference conference,
struct confbridge_user user,
int  mute 
) [static]

Definition at line 2499 of file app_confbridge.c.

References ast_channel_name(), ast_test_suite_event_notify, confbridge_conference::b_profile, confbridge_user::chan, conf_update_user_mute(), confbridge_user::muted, bridge_profile::name, send_mute_event(), and send_unmute_event().

Referenced by generic_mute_unmute_helper().

02500 {
02501    /* Set user level mute request. */
02502    user->muted = mute ? 1 : 0;
02503 
02504    conf_update_user_mute(user);
02505    ast_test_suite_event_notify("CONF_MUTE",
02506       "Message: participant %s %s\r\n"
02507       "Conference: %s\r\n"
02508       "Channel: %s",
02509       ast_channel_name(user->chan),
02510       mute ? "muted" : "unmuted",
02511       conference->b_profile.name,
02512       ast_channel_name(user->chan));
02513    if (mute) {
02514       send_mute_event(user, conference);
02515    } else {
02516       send_unmute_event(user, conference);
02517    }
02518 }

static char* handle_cli_confbridge_kick ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2322 of file app_confbridge.c.

References ao2_find, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), complete_confbridge_participant(), ast_cli_args::fd, kick_conference_participant(), ast_cli_args::line, ast_cli_args::n, NULL, OBJ_KEY, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

02323 {
02324    struct confbridge_conference *conference;
02325    int not_found;
02326 
02327    switch (cmd) {
02328    case CLI_INIT:
02329       e->command = "confbridge kick";
02330       e->usage =
02331          "Usage: confbridge kick <conference> <channel>\n"
02332          "       Kicks a channel out of the conference bridge.\n"
02333          "             (all to kick everyone, participants to kick non-admins).\n";
02334       return NULL;
02335    case CLI_GENERATE:
02336       if (a->pos == 2) {
02337          return complete_confbridge_name(a->line, a->word, a->pos, a->n);
02338       }
02339       if (a->pos == 3) {
02340          return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
02341       }
02342       return NULL;
02343    }
02344 
02345    if (a->argc != 4) {
02346       return CLI_SHOWUSAGE;
02347    }
02348 
02349    conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
02350    if (!conference) {
02351       ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
02352       return CLI_SUCCESS;
02353    }
02354    not_found = kick_conference_participant(conference, a->argv[3]);
02355    ao2_ref(conference, -1);
02356    if (not_found) {
02357       if (!strcasecmp("all", a->argv[3]) || !strcasecmp("participants", a->argv[3])) {
02358          ast_cli(a->fd, "No participants found!\n");
02359       } else {
02360          ast_cli(a->fd, "No participant named '%s' found!\n", a->argv[3]);
02361       }
02362       return CLI_SUCCESS;
02363    }
02364    ast_cli(a->fd, "Kicked '%s' out of conference '%s'\n", a->argv[3], a->argv[2]);
02365    return CLI_SUCCESS;
02366 }

static char* handle_cli_confbridge_list ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2404 of file app_confbridge.c.

References confbridge_conference::active_list, confbridge_conference::activeusers, ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), AST_LIST_TRAVERSE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), ast_cli_args::fd, handle_cli_confbridge_list_item(), ast_cli_args::line, confbridge_user::list, confbridge_conference::locked, confbridge_conference::markedusers, ast_cli_args::n, confbridge_conference::name, NULL, OBJ_KEY, ast_cli_args::pos, ast_cli_entry::usage, confbridge_conference::waiting_list, confbridge_conference::waitingusers, and ast_cli_args::word.

02405 {
02406    struct confbridge_conference *conference;
02407 
02408    switch (cmd) {
02409    case CLI_INIT:
02410       e->command = "confbridge list";
02411       e->usage =
02412          "Usage: confbridge list [<name>]\n"
02413          "       Lists all currently active conference bridges or a specific conference bridge.\n"
02414          "\n"
02415          "       When a conference bridge name is provided, flags may be shown for users. Below\n"
02416          "       are the flags and what they represent.\n"
02417          "\n"
02418          "       Flags:\n"
02419          "         A - The user is an admin\n"
02420          "         M - The user is a marked user\n"
02421          "         W - The user must wait for a marked user to join\n"
02422          "         E - The user will be kicked after the last marked user leaves the conference\n"
02423          "         m - The user is muted\n"
02424          "         w - The user is waiting for a marked user to join\n";
02425       return NULL;
02426    case CLI_GENERATE:
02427       if (a->pos == 2) {
02428          return complete_confbridge_name(a->line, a->word, a->pos, a->n);
02429       }
02430       return NULL;
02431    }
02432 
02433    if (a->argc == 2) {
02434       struct ao2_iterator iter;
02435 
02436       ast_cli(a->fd, "Conference Bridge Name           Users  Marked Locked?\n");
02437       ast_cli(a->fd, "================================ ====== ====== ========\n");
02438       iter = ao2_iterator_init(conference_bridges, 0);
02439       while ((conference = ao2_iterator_next(&iter))) {
02440          ast_cli(a->fd, "%-32s %6u %6u %s\n", conference->name, conference->activeusers + conference->waitingusers, conference->markedusers, (conference->locked ? "locked" : "unlocked"));
02441          ao2_ref(conference, -1);
02442       }
02443       ao2_iterator_destroy(&iter);
02444       return CLI_SUCCESS;
02445    }
02446 
02447    if (a->argc == 3) {
02448       struct confbridge_user *user;
02449 
02450       conference = ao2_find(conference_bridges, a->argv[2], OBJ_KEY);
02451       if (!conference) {
02452          ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
02453          return CLI_SUCCESS;
02454       }
02455       ast_cli(a->fd, "Channel                        Flags  User Profile     Bridge Profile   Menu             CallerID\n");
02456       ast_cli(a->fd, "============================== ====== ================ ================ ================ ================\n");
02457       ao2_lock(conference);
02458       AST_LIST_TRAVERSE(&conference->active_list, user, list) {
02459          handle_cli_confbridge_list_item(a, user, 0);
02460       }
02461       AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
02462          handle_cli_confbridge_list_item(a, user, 1);
02463       }
02464       ao2_unlock(conference);
02465       ao2_ref(conference, -1);
02466       return CLI_SUCCESS;
02467    }
02468 
02469    return CLI_SHOWUSAGE;
02470 }

static void handle_cli_confbridge_list_item ( struct ast_cli_args a,
struct confbridge_user user,
int  waiting 
) [static]

Definition at line 2368 of file app_confbridge.c.

References ast_channel_caller(), ast_channel_name(), ast_cli(), ast_test_flag, confbridge_user::b_profile, confbridge_user::chan, ast_cli_args::fd, ast_party_caller::id, confbridge_user::menu_name, confbridge_user::muted, bridge_profile::name, user_profile::name, ast_party_id::number, S_COR, ast_party_number::str, confbridge_user::u_profile, USER_OPT_ADMIN, USER_OPT_ENDMARKED, USER_OPT_MARKEDUSER, USER_OPT_WAITMARKED, and ast_party_number::valid.

Referenced by handle_cli_confbridge_list().

02369 {
02370    char flag_str[6 + 1];/* Max flags + terminator */
02371    int pos = 0;
02372 
02373    /* Build flags column string. */
02374    if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
02375       flag_str[pos++] = 'A';
02376    }
02377    if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
02378       flag_str[pos++] = 'M';
02379    }
02380    if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
02381       flag_str[pos++] = 'W';
02382    }
02383    if (ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED)) {
02384       flag_str[pos++] = 'E';
02385    }
02386    if (user->muted) {
02387       flag_str[pos++] = 'm';
02388    }
02389    if (waiting) {
02390       flag_str[pos++] = 'w';
02391    }
02392    flag_str[pos] = '\0';
02393 
02394    ast_cli(a->fd, "%-30s %-6s %-16s %-16s %-16s %s\n",
02395       ast_channel_name(user->chan),
02396       flag_str,
02397       user->u_profile.name,
02398       user->b_profile.name,
02399       user->menu_name,
02400       S_COR(ast_channel_caller(user->chan)->id.number.valid,
02401          ast_channel_caller(user->chan)->id.number.str, "<unknown>"));
02402 }

static char* handle_cli_confbridge_lock ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2654 of file app_confbridge.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), ast_cli_args::fd, generic_lock_unlock_helper(), ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

02655 {
02656    switch (cmd) {
02657    case CLI_INIT:
02658       e->command = "confbridge lock";
02659       e->usage =
02660          "Usage: confbridge lock <conference>\n"
02661          "       Lock a conference. While locked, no new non-admins\n"
02662          "       may join the conference.\n";
02663       return NULL;
02664    case CLI_GENERATE:
02665       if (a->pos == 2) {
02666          return complete_confbridge_name(a->line, a->word, a->pos, a->n);
02667       }
02668       return NULL;
02669    }
02670    if (a->argc != 3) {
02671       return CLI_SHOWUSAGE;
02672    }
02673    if (generic_lock_unlock_helper(1, a->argv[2])) {
02674       ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
02675    } else {
02676       ast_cli(a->fd, "Conference %s is locked.\n", a->argv[2]);
02677    }
02678    return CLI_SUCCESS;
02679 }

static char* handle_cli_confbridge_mute ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2592 of file app_confbridge.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, cli_mute_unmute_helper(), CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), complete_confbridge_participant(), ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

02593 {
02594    switch (cmd) {
02595    case CLI_INIT:
02596       e->command = "confbridge mute";
02597       e->usage =
02598          "Usage: confbridge mute <conference> <channel>\n"
02599          "       Mute a channel in a conference.\n"
02600          "              (all to mute everyone, participants to mute non-admins)\n"
02601          "       If the specified channel is a prefix,\n"
02602          "       the action will be taken on the first\n"
02603          "       matching channel.\n";
02604       return NULL;
02605    case CLI_GENERATE:
02606       if (a->pos == 2) {
02607          return complete_confbridge_name(a->line, a->word, a->pos, a->n);
02608       }
02609       if (a->pos == 3) {
02610          return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
02611       }
02612       return NULL;
02613    }
02614    if (a->argc != 4) {
02615       return CLI_SHOWUSAGE;
02616    }
02617 
02618    cli_mute_unmute_helper(1, a);
02619 
02620    return CLI_SUCCESS;
02621 }

static char* handle_cli_confbridge_start_record ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2707 of file app_confbridge.c.

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), ast_strlen_zero, confbridge_conference::b_profile, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), conf_is_recording(), conf_start_record(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NULL, OBJ_KEY, ast_cli_args::pos, bridge_profile::rec_file, ast_cli_entry::usage, and ast_cli_args::word.

02708 {
02709    const char *rec_file = NULL;
02710    struct confbridge_conference *conference;
02711 
02712    switch (cmd) {
02713    case CLI_INIT:
02714       e->command = "confbridge record start";
02715       e->usage =
02716          "Usage: confbridge record start <conference> <file>\n"
02717          "       <file> is optional, Otherwise the bridge profile\n"
02718          "       record file will be used.  If the bridge profile\n"
02719          "       has no record file specified, a file will automatically\n"
02720          "       be generated in the monitor directory\n";
02721       return NULL;
02722    case CLI_GENERATE:
02723       if (a->pos == 3) {
02724          return complete_confbridge_name(a->line, a->word, a->pos, a->n);
02725       }
02726       return NULL;
02727    }
02728    if (a->argc < 4) {
02729       return CLI_SHOWUSAGE;
02730    }
02731    if (a->argc == 5) {
02732       rec_file = a->argv[4];
02733    }
02734 
02735    conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
02736    if (!conference) {
02737       ast_cli(a->fd, "Conference not found.\n");
02738       return CLI_FAILURE;
02739    }
02740    ao2_lock(conference);
02741    if (conf_is_recording(conference)) {
02742       ast_cli(a->fd, "Conference is already being recorded.\n");
02743       ao2_unlock(conference);
02744       ao2_ref(conference, -1);
02745       return CLI_SUCCESS;
02746    }
02747    if (!ast_strlen_zero(rec_file)) {
02748       ast_copy_string(conference->b_profile.rec_file, rec_file, sizeof(conference->b_profile.rec_file));
02749    }
02750 
02751    if (conf_start_record(conference)) {
02752       ast_cli(a->fd, "Could not start recording due to internal error.\n");
02753       ao2_unlock(conference);
02754       ao2_ref(conference, -1);
02755       return CLI_FAILURE;
02756    }
02757    ao2_unlock(conference);
02758 
02759    ast_cli(a->fd, "Recording started\n");
02760    ao2_ref(conference, -1);
02761    return CLI_SUCCESS;
02762 }

static char* handle_cli_confbridge_stop_record ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2764 of file app_confbridge.c.

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), conf_stop_record(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, NULL, OBJ_KEY, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

02765 {
02766    struct confbridge_conference *conference;
02767    int ret;
02768 
02769    switch (cmd) {
02770    case CLI_INIT:
02771       e->command = "confbridge record stop";
02772       e->usage =
02773          "Usage: confbridge record stop <conference>\n"
02774          "       Stop a previously started recording.\n";
02775       return NULL;
02776    case CLI_GENERATE:
02777       if (a->pos == 3) {
02778          return complete_confbridge_name(a->line, a->word, a->pos, a->n);
02779       }
02780       return NULL;
02781    }
02782    if (a->argc != 4) {
02783       return CLI_SHOWUSAGE;
02784    }
02785 
02786    conference = ao2_find(conference_bridges, a->argv[3], OBJ_KEY);
02787    if (!conference) {
02788       ast_cli(a->fd, "Conference not found.\n");
02789       return CLI_SUCCESS;
02790    }
02791    ao2_lock(conference);
02792    ret = conf_stop_record(conference);
02793    ao2_unlock(conference);
02794    ast_cli(a->fd, "Recording %sstopped.\n", ret ? "could not be " : "");
02795    ao2_ref(conference, -1);
02796    return CLI_SUCCESS;
02797 }

static char* handle_cli_confbridge_unlock ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2681 of file app_confbridge.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), ast_cli_args::fd, generic_lock_unlock_helper(), ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

02682 {
02683    switch (cmd) {
02684    case CLI_INIT:
02685       e->command = "confbridge unlock";
02686       e->usage =
02687          "Usage: confbridge unlock <conference>\n"
02688          "       Unlock a previously locked conference.\n";
02689       return NULL;
02690    case CLI_GENERATE:
02691       if (a->pos == 2) {
02692          return complete_confbridge_name(a->line, a->word, a->pos, a->n);
02693       }
02694       return NULL;
02695    }
02696    if (a->argc != 3) {
02697       return CLI_SHOWUSAGE;
02698    }
02699    if (generic_lock_unlock_helper(0, a->argv[2])) {
02700       ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]);
02701    } else {
02702       ast_cli(a->fd, "Conference %s is unlocked.\n", a->argv[2]);
02703    }
02704    return CLI_SUCCESS;
02705 }

static char* handle_cli_confbridge_unmute ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 2623 of file app_confbridge.c.

References ast_cli_args::argc, ast_cli_args::argv, CLI_GENERATE, CLI_INIT, cli_mute_unmute_helper(), CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), complete_confbridge_participant(), ast_cli_args::line, ast_cli_args::n, NULL, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

02624 {
02625    switch (cmd) {
02626    case CLI_INIT:
02627       e->command = "confbridge unmute";
02628       e->usage =
02629          "Usage: confbridge unmute <conference> <channel>\n"
02630          "       Unmute a channel in a conference.\n"
02631          "              (all to unmute everyone, participants to unmute non-admins)\n"
02632          "       If the specified channel is a prefix,\n"
02633          "       the action will be taken on the first\n"
02634          "       matching channel.\n";
02635       return NULL;
02636    case CLI_GENERATE:
02637       if (a->pos == 2) {
02638          return complete_confbridge_name(a->line, a->word, a->pos, a->n);
02639       }
02640       if (a->pos == 3) {
02641          return complete_confbridge_participant(a->argv[2], a->line, a->word, a->pos, a->n);
02642       }
02643       return NULL;
02644    }
02645    if (a->argc != 4) {
02646       return CLI_SHOWUSAGE;
02647    }
02648 
02649    cli_mute_unmute_helper(0, a);
02650 
02651    return CLI_SUCCESS;
02652 }

static int handle_conf_user_join ( struct confbridge_user user  )  [static]

Call the proper join event handler for the user for the conference bridge's current state.

Definition at line 966 of file app_confbridge.c.

References ast_assert, ast_test_flag, conf_invalid_event_fn(), confbridge_user::conference, handler(), confbridge_state::join_marked, confbridge_state::join_unmarked, confbridge_state::join_waitmarked, NULL, confbridge_conference::state, confbridge_user::u_profile, USER_OPT_MARKEDUSER, and USER_OPT_WAITMARKED.

Referenced by join_conference_bridge().

00967 {
00968    conference_event_fn handler;
00969    if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
00970       handler = user->conference->state->join_marked;
00971    } else if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
00972       handler = user->conference->state->join_waitmarked;
00973    } else {
00974       handler = user->conference->state->join_unmarked;
00975    }
00976 
00977    ast_assert(handler != NULL);
00978 
00979    if (!handler) {
00980       conf_invalid_event_fn(user);
00981       return -1;
00982    }
00983 
00984    handler(user);
00985 
00986    return 0;
00987 }

static int handle_conf_user_leave ( struct confbridge_user user  )  [static]

Call the proper leave event handler for the user for the conference bridge's current state.

Definition at line 995 of file app_confbridge.c.

References ast_assert, ast_test_flag, conf_invalid_event_fn(), confbridge_user::conference, handler(), confbridge_state::leave_marked, confbridge_state::leave_unmarked, confbridge_state::leave_waitmarked, NULL, confbridge_conference::state, confbridge_user::u_profile, USER_OPT_MARKEDUSER, and USER_OPT_WAITMARKED.

Referenced by leave_conference().

00996 {
00997    conference_event_fn handler;
00998    if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
00999       handler = user->conference->state->leave_marked;
01000    } else if (ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)) {
01001       handler = user->conference->state->leave_waitmarked;
01002    } else {
01003       handler = user->conference->state->leave_unmarked;
01004    }
01005 
01006    ast_assert(handler != NULL);
01007 
01008    if (!handler) {
01009       /* This should never happen. If it does, though, it is bad. The user will not have been removed
01010        * from the appropriate list, so counts will be off and stuff. The conference won't be torn down, etc.
01011        * Shouldn't happen, though. */
01012       conf_invalid_event_fn(user);
01013       return -1;
01014    }
01015 
01016    handler(user);
01017 
01018    return 0;
01019 }

static void handle_video_on_exit ( struct confbridge_conference conference,
struct ast_channel chan 
) [static]

Definition at line 889 of file app_confbridge.c.

References confbridge_conference::active_list, ao2_lock, ao2_unlock, ast_bridge_is_video_src(), ast_bridge_remove_video_src(), ast_bridge_set_single_src_video_mode(), ast_bridge_set_talker_src_video_mode(), AST_LIST_TRAVERSE, ast_test_flag, confbridge_conference::b_profile, confbridge_conference::bridge, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED, confbridge_user::chan, confbridge_user::list, NULL, confbridge_user::u_profile, and USER_OPT_MARKEDUSER.

Referenced by confbridge_exec(), and execute_menu_entry().

00890 {
00891    struct confbridge_user *user = NULL;
00892 
00893    /* if this isn't a video source, nothing to update */
00894    if (!ast_bridge_is_video_src(conference->bridge, chan)) {
00895       return;
00896    }
00897 
00898    ast_bridge_remove_video_src(conference->bridge, chan);
00899 
00900    /* If in follow talker mode, make sure to restore this mode on the
00901     * bridge when a source is removed.  It is possible this channel was
00902     * only set temporarily as a video source by an AMI or DTMF action. */
00903    if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
00904       ast_bridge_set_talker_src_video_mode(conference->bridge);
00905    }
00906 
00907    /* if the video_mode isn't set to automatically pick the video source, do nothing on exit. */
00908    if (!ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) &&
00909       !ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
00910       return;
00911    }
00912 
00913    /* Make the next available marked user the video src.  */
00914    ao2_lock(conference);
00915    AST_LIST_TRAVERSE(&conference->active_list, user, list) {
00916       if (user->chan == chan) {
00917          continue;
00918       }
00919       if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
00920          ast_bridge_set_single_src_video_mode(conference->bridge, user->chan);
00921          break;
00922       }
00923    }
00924    ao2_unlock(conference);
00925 }

static void handle_video_on_join ( struct confbridge_conference conference,
struct ast_channel chan,
int  marked 
) [static]

Definition at line 857 of file app_confbridge.c.

References confbridge_conference::active_list, ao2_lock, ao2_unlock, ast_bridge_is_video_src(), ast_bridge_set_single_src_video_mode(), AST_LIST_TRAVERSE, ast_test_flag, confbridge_conference::b_profile, confbridge_conference::bridge, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED, confbridge_user::chan, confbridge_user::list, and NULL.

Referenced by confbridge_exec().

00858 {
00859    /* Right now, only marked users are automatically set as the single src of video.*/
00860    if (!marked) {
00861       return;
00862    }
00863 
00864    if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED)) {
00865       int set = 1;
00866       struct confbridge_user *user = NULL;
00867 
00868       ao2_lock(conference);
00869       /* see if anyone is already the video src */
00870       AST_LIST_TRAVERSE(&conference->active_list, user, list) {
00871          if (user->chan == chan) {
00872             continue;
00873          }
00874          if (ast_bridge_is_video_src(conference->bridge, user->chan)) {
00875             set = 0;
00876             break;
00877          }
00878       }
00879       ao2_unlock(conference);
00880       if (set) {
00881          ast_bridge_set_single_src_video_mode(conference->bridge, chan);
00882       }
00883    } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) {
00884       /* we joined and are video capable, we override anyone else that may have already been the video feed */
00885       ast_bridge_set_single_src_video_mode(conference->bridge, chan);
00886    }
00887 }

static int is_new_rec_file ( const char *  rec_file,
struct ast_str **  orig_rec_file 
) [static]

Definition at line 590 of file app_confbridge.c.

References ast_str_buffer(), ast_str_create(), ast_str_set(), ast_strlen_zero, and RECORD_FILENAME_INITIAL_SPACE.

Referenced by conf_start_record().

00591 {
00592    if (!ast_strlen_zero(rec_file)) {
00593       if (!*orig_rec_file) {
00594          *orig_rec_file = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
00595       }
00596 
00597       if (*orig_rec_file
00598          && strcmp(ast_str_buffer(*orig_rec_file), rec_file)) {
00599          ast_str_set(orig_rec_file, 0, "%s", rec_file);
00600          return 1;
00601       }
00602    }
00603    return 0;
00604 }

static struct confbridge_conference* join_conference_bridge ( const char *  conference_name,
struct confbridge_user user 
) [static, read]

Join a conference bridge.

Parameters:
conference_name The conference name
user Conference bridge user structure
Returns:
A pointer to the conference bridge struct, or NULL if the conference room wasn't found.

Definition at line 1212 of file app_confbridge.c.

References confbridge_conference::activeusers, announce_user_count(), user_profile::announce_user_count_all_after, user_profile::announcement, ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_autoservice_start(), ast_autoservice_stop(), ast_bridge_base_new(), AST_BRIDGE_CAPABILITY_MULTIMIX, AST_BRIDGE_FLAG_MASQUERADE_ONLY, AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY, ast_bridge_set_internal_sample_rate(), ast_bridge_set_mixing_interval(), ast_bridge_set_talker_src_video_mode(), ast_check_hangup(), ast_copy_string(), ast_debug, ast_free, AST_LIST_REMOVE_HEAD, ast_log, ast_mutex_init, ast_str_create(), ast_stream_and_wait(), ast_strlen_zero, ast_test_flag, confbridge_user::b_profile, confbridge_conference::b_profile, confbridge_conference::bridge, BRIDGE_OPT_RECORD_CONFERENCE, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER, confbridge_user::chan, conf_bridge_profile_copy(), conf_get_sound(), CONF_SOUND_LOCKED, conf_start_record(), CONF_STATE_EMPTY, confbridge_user::conference, destroy_conference_bridge(), post_join_action::func, handle_conf_user_join(), bridge_profile::internal_sample_rate, leave_conference(), post_join_action::list, confbridge_conference::locked, LOG_ERROR, bridge_profile::max_members, bridge_profile::mix_interval, confbridge_conference::name, NULL, OBJ_KEY, play_prompt_to_user(), confbridge_conference::playback_lock, confbridge_user::post_join_list, confbridge_conference::record_filename, RECORD_FILENAME_INITIAL_SPACE, send_conf_start_event(), bridge_profile::sounds, confbridge_conference::state, confbridge_user::suspended_moh, confbridge_user::u_profile, USER_OPT_ADMIN, USER_OPT_ANNOUNCEUSERCOUNT, and USER_OPT_ANNOUNCEUSERCOUNTALL.

Referenced by confbridge_exec().

01213 {
01214    struct confbridge_conference *conference;
01215    struct post_join_action *action;
01216    int max_members_reached = 0;
01217 
01218    /* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */
01219    ao2_lock(conference_bridges);
01220 
01221    ast_debug(1, "Trying to find conference bridge '%s'\n", conference_name);
01222 
01223    /* Attempt to find an existing conference bridge */
01224    conference = ao2_find(conference_bridges, conference_name, OBJ_KEY);
01225    if (conference && conference->b_profile.max_members) {
01226       max_members_reached = conference->b_profile.max_members > conference->activeusers ? 0 : 1;
01227    }
01228 
01229    /* When finding a conference bridge that already exists make sure that it is not locked, and if so that we are not an admin */
01230    if (conference && (max_members_reached || conference->locked) && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
01231       ao2_unlock(conference_bridges);
01232       ao2_ref(conference, -1);
01233       ast_debug(1, "Conference '%s' is locked and caller is not an admin\n", conference_name);
01234       ast_stream_and_wait(user->chan,
01235             conf_get_sound(CONF_SOUND_LOCKED, user->b_profile.sounds),
01236             "");
01237       return NULL;
01238    }
01239 
01240    /* If no conference bridge was found see if we can create one */
01241    if (!conference) {
01242       /* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */
01243       if (!(conference = ao2_alloc(sizeof(*conference), destroy_conference_bridge))) {
01244          ao2_unlock(conference_bridges);
01245          ast_log(LOG_ERROR, "Conference '%s' could not be created.\n", conference_name);
01246          return NULL;
01247       }
01248 
01249       /* Setup lock for playback channel */
01250       ast_mutex_init(&conference->playback_lock);
01251 
01252       /* Setup for the record channel */
01253       conference->record_filename = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
01254       if (!conference->record_filename) {
01255          ao2_ref(conference, -1);
01256          ao2_unlock(conference_bridges);
01257          return NULL;
01258       }
01259 
01260       /* Setup conference bridge parameters */
01261       ast_copy_string(conference->name, conference_name, sizeof(conference->name));
01262       conf_bridge_profile_copy(&conference->b_profile, &user->b_profile);
01263 
01264       /* Create an actual bridge that will do the audio mixing */
01265       conference->bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_MULTIMIX,
01266          AST_BRIDGE_FLAG_MASQUERADE_ONLY | AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY,
01267          app, conference_name, NULL);
01268       if (!conference->bridge) {
01269          ao2_ref(conference, -1);
01270          conference = NULL;
01271          ao2_unlock(conference_bridges);
01272          ast_log(LOG_ERROR, "Conference '%s' mixing bridge could not be created.\n", conference_name);
01273          return NULL;
01274       }
01275 
01276       /* Set the internal sample rate on the bridge from the bridge profile */
01277       ast_bridge_set_internal_sample_rate(conference->bridge, conference->b_profile.internal_sample_rate);
01278       /* Set the internal mixing interval on the bridge from the bridge profile */
01279       ast_bridge_set_mixing_interval(conference->bridge, conference->b_profile.mix_interval);
01280 
01281       if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) {
01282          ast_bridge_set_talker_src_video_mode(conference->bridge);
01283       }
01284 
01285       /* Link it into the conference bridges container */
01286       if (!ao2_link(conference_bridges, conference)) {
01287          ao2_ref(conference, -1);
01288          conference = NULL;
01289          ao2_unlock(conference_bridges);
01290          ast_log(LOG_ERROR,
01291             "Conference '%s' could not be added to the conferences list.\n", conference_name);
01292          return NULL;
01293       }
01294 
01295       /* Set the initial state to EMPTY */
01296       conference->state = CONF_STATE_EMPTY;
01297 
01298       if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_CONFERENCE)) {
01299          ao2_lock(conference);
01300          conf_start_record(conference);
01301          ao2_unlock(conference);
01302       }
01303 
01304       send_conf_start_event(conference);
01305       ast_debug(1, "Created conference '%s' and linked to container.\n", conference_name);
01306    }
01307 
01308    ao2_unlock(conference_bridges);
01309 
01310    /* Setup conference bridge user parameters */
01311    user->conference = conference;
01312 
01313    ao2_lock(conference);
01314 
01315    /*
01316     * Suspend any MOH until the user actually joins the bridge of
01317     * the conference.  This way any pre-join file playback does not
01318     * need to worry about MOH.
01319     */
01320    user->suspended_moh = 1;
01321 
01322    if (handle_conf_user_join(user)) {
01323       /* Invalid event, nothing was done, so we don't want to process a leave. */
01324       ao2_unlock(conference);
01325       ao2_ref(conference, -1);
01326       return NULL;
01327    }
01328 
01329    if (ast_check_hangup(user->chan)) {
01330       ao2_unlock(conference);
01331       leave_conference(user);
01332       return NULL;
01333    }
01334 
01335    ao2_unlock(conference);
01336 
01337    /* If an announcement is to be played play it */
01338    if (!ast_strlen_zero(user->u_profile.announcement)) {
01339       if (play_prompt_to_user(user,
01340          user->u_profile.announcement)) {
01341          leave_conference(user);
01342          return NULL;
01343       }
01344    }
01345 
01346    /* Announce number of users if need be */
01347    if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
01348       if (announce_user_count(conference, user, NULL)) {
01349          leave_conference(user);
01350          return NULL;
01351       }
01352    }
01353 
01354    if (ast_test_flag(&user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
01355       (conference->activeusers > user->u_profile.announce_user_count_all_after)) {
01356       int user_count_res;
01357 
01358       /*
01359        * We have to autoservice the new user because he has not quite
01360        * joined the conference yet.
01361        */
01362       ast_autoservice_start(user->chan);
01363       user_count_res = announce_user_count(conference, NULL, NULL);
01364       ast_autoservice_stop(user->chan);
01365       if (user_count_res) {
01366          leave_conference(user);
01367          return NULL;
01368       }
01369    }
01370 
01371    /* Handle post-join actions */
01372    while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
01373       action->func(user);
01374       ast_free(action);
01375    }
01376 
01377    return conference;
01378 }

static int kick_conference_participant ( struct confbridge_conference conference,
const char *  channel 
) [static]

Definition at line 2213 of file app_confbridge.c.

References confbridge_conference::active_list, ast_bridge_remove(), ast_channel_name(), AST_LIST_TRAVERSE, ast_test_flag, confbridge_conference::bridge, confbridge_user::chan, confbridge_user::kicked, confbridge_user::list, match(), NULL, pbx_builtin_setvar_helper(), SCOPED_AO2LOCK, confbridge_user::u_profile, USER_OPT_ADMIN, and confbridge_conference::waiting_list.

Referenced by action_confbridgekick(), and handle_cli_confbridge_kick().

02215 {
02216    int res = -1;
02217    int match;
02218    struct confbridge_user *user = NULL;
02219    int all = !strcasecmp("all", channel);
02220    int participants = !strcasecmp("participants", channel);
02221 
02222    SCOPED_AO2LOCK(bridge_lock, conference);
02223 
02224    AST_LIST_TRAVERSE(&conference->active_list, user, list) {
02225       if (user->kicked) {
02226          continue;
02227       }
02228       match = !strcasecmp(channel, ast_channel_name(user->chan));
02229       if (match || all
02230             || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
02231          user->kicked = 1;
02232          pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
02233          ast_bridge_remove(conference->bridge, user->chan);
02234          res = 0;
02235          if (match) {
02236             return res;
02237          }
02238       }
02239    }
02240    AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
02241       if (user->kicked) {
02242          continue;
02243       }
02244       match = !strcasecmp(channel, ast_channel_name(user->chan));
02245       if (match || all
02246             || (participants && !ast_test_flag(&user->u_profile, USER_OPT_ADMIN))) {
02247          user->kicked = 1;
02248          pbx_builtin_setvar_helper(user->chan, "CONFBRIDGE_RESULT", "KICKED");
02249          ast_bridge_remove(conference->bridge, user->chan);
02250          res = 0;
02251          if (match) {
02252             return res;
02253          }
02254       }
02255    }
02256 
02257    return res;
02258 }

static void leave_conference ( struct confbridge_user user  )  [static]

Leave a conference.

Parameters:
user The conference user

Definition at line 1385 of file app_confbridge.c.

References ao2_lock, ao2_ref, ao2_unlock, ast_free, AST_LIST_REMOVE_HEAD, confbridge_user::conference, handle_conf_user_leave(), post_join_action::list, NULL, and confbridge_user::post_join_list.

Referenced by confbridge_exec(), and join_conference_bridge().

01386 {
01387    struct post_join_action *action;
01388 
01389    ao2_lock(user->conference);
01390    handle_conf_user_leave(user);
01391    ao2_unlock(user->conference);
01392 
01393    /* Discard any post-join actions */
01394    while ((action = AST_LIST_REMOVE_HEAD(&user->post_join_list, list))) {
01395       ast_free(action);
01396    }
01397 
01398    /* Done mucking with the conference, huzzah */
01399    ao2_ref(user->conference, -1);
01400    user->conference = NULL;
01401 }

static int load_module ( void   )  [static]

Load the module.

Module loading including tests for configuration or dependencies. This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE, or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails tests return AST_MODULE_LOAD_FAILURE. If the module can not load the configuration file or other non-critical problem return AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.

Definition at line 3372 of file app_confbridge.c.

References action_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgelock(), action_confbridgemute(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_confbridgeunlock(), action_confbridgeunmute(), ao2_container_alloc, ARRAY_LEN, AST_CFE_WRITE, ast_cli_register_multiple(), ast_custom_function_register, ast_custom_function_register_escalating, ast_log, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, conf_announce_get_tech(), conf_load_config(), conf_record_get_tech(), confbridge_exec(), CONFERENCE_BRIDGE_BUCKETS, conference_bridge_cmp_cb(), conference_bridge_hash_cb(), EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, LOG_ERROR, manager_confbridge_init(), register_channel_tech(), and unload_module.

03373 {
03374    int res = 0;
03375 
03376    if (conf_load_config()) {
03377       ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n");
03378       return AST_MODULE_LOAD_DECLINE;
03379    }
03380 
03381    if (register_channel_tech(conf_record_get_tech())
03382       || register_channel_tech(conf_announce_get_tech())) {
03383       unload_module();
03384       return AST_MODULE_LOAD_FAILURE;
03385    }
03386 
03387    /* Create a container to hold the conference bridges */
03388    conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS,
03389       conference_bridge_hash_cb, conference_bridge_cmp_cb);
03390    if (!conference_bridges) {
03391       unload_module();
03392       return AST_MODULE_LOAD_FAILURE;
03393    }
03394 
03395    /* Setup manager stasis subscriptions */
03396    res |= manager_confbridge_init();
03397 
03398    res |= ast_register_application_xml(app, confbridge_exec);
03399 
03400    res |= ast_custom_function_register_escalating(&confbridge_function, AST_CFE_WRITE);
03401    res |= ast_custom_function_register(&confbridge_info_function);
03402 
03403    res |= ast_cli_register_multiple(cli_confbridge, ARRAY_LEN(cli_confbridge));
03404 
03405    res |= ast_manager_register_xml("ConfbridgeList", EVENT_FLAG_REPORTING, action_confbridgelist);
03406    res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms);
03407    res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute);
03408    res |= ast_manager_register_xml("ConfbridgeUnmute", EVENT_FLAG_CALL, action_confbridgeunmute);
03409    res |= ast_manager_register_xml("ConfbridgeKick", EVENT_FLAG_CALL, action_confbridgekick);
03410    res |= ast_manager_register_xml("ConfbridgeUnlock", EVENT_FLAG_CALL, action_confbridgeunlock);
03411    res |= ast_manager_register_xml("ConfbridgeLock", EVENT_FLAG_CALL, action_confbridgelock);
03412    res |= ast_manager_register_xml("ConfbridgeStartRecord", EVENT_FLAG_SYSTEM, action_confbridgestartrecord);
03413    res |= ast_manager_register_xml("ConfbridgeStopRecord", EVENT_FLAG_SYSTEM, action_confbridgestoprecord);
03414    res |= ast_manager_register_xml("ConfbridgeSetSingleVideoSrc", EVENT_FLAG_CALL, action_confbridgesetsinglevideosrc);
03415    if (res) {
03416       unload_module();
03417       return AST_MODULE_LOAD_FAILURE;
03418    }
03419 
03420    return AST_MODULE_LOAD_SUCCESS;
03421 }

static int play_file ( struct ast_bridge_channel bridge_channel,
struct ast_channel channel,
const char *  filename 
) [static]

Definition at line 742 of file app_confbridge.c.

References ast_bridge_channel_feature_digit_add(), AST_DIGIT_ANY, AST_DIGIT_NONE, ast_log, ast_stopstream(), ast_stream_and_wait(), ast_bridge_channel::chan, digit, and LOG_WARNING.

Referenced by action_kick_last(), action_toggle_mute(), announce_user_count(), check_bridge_play_sound(), execute_menu_entry(), say_periodic_announcement(), say_position(), and try_calling().

00744 {
00745    struct ast_channel *chan;
00746    const char *stop_digits;
00747    int digit;
00748 
00749    if (bridge_channel) {
00750       chan = bridge_channel->chan;
00751       stop_digits = AST_DIGIT_ANY;
00752    } else {
00753       chan = channel;
00754       stop_digits = AST_DIGIT_NONE;
00755    }
00756 
00757    digit = ast_stream_and_wait(chan, filename, stop_digits);
00758    if (digit < 0) {
00759       ast_log(LOG_WARNING, "Failed to playback file '%s' to channel\n", filename);
00760       return -1;
00761    }
00762 
00763    if (digit > 0) {
00764       ast_stopstream(bridge_channel->chan);
00765       ast_bridge_channel_feature_digit_add(bridge_channel, digit);
00766       return 1;
00767    }
00768 
00769    return 0;
00770 }

static int play_prompt_to_user ( struct confbridge_user user,
const char *  filename 
) [static]

Play back an audio file to a channel.

Parameters:
user User to play audio prompt to
filename Prompt to play
Returns:
Returns 0 on success, -1 if the user hung up
Note:
Generally this should be called when the conference is unlocked to avoid blocking the entire conference while the sound is played. But don't unlock the conference bridge in the middle of a state transition.

Definition at line 852 of file app_confbridge.c.

References ast_stream_and_wait(), and confbridge_user::chan.

Referenced by conf_handle_inactive_waitmarked(), conf_handle_only_unmarked(), and join_conference_bridge().

00853 {
00854    return ast_stream_and_wait(user->chan, filename, "");
00855 }

int play_sound_file ( struct confbridge_conference conference,
const char *  filename 
)

Play sound file into conference bridge.

Parameters:
conference The conference bridge to play sound file into
filename Sound file to play
Return values:
0 success
-1 failure

Definition at line 1468 of file app_confbridge.c.

References play_sound_helper().

Referenced by announce_user_count(), confbridge_exec(), leave_marked(), and post_join_play_begin().

01469 {
01470    return play_sound_helper(conference, filename, -1);
01471 }

static int play_sound_helper ( struct confbridge_conference conference,
const char *  filename,
int  say_number 
) [static]

Definition at line 1434 of file app_confbridge.c.

References alloc_playback_chan(), ast_channel_language(), ast_channel_name(), ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_say_number(), ast_stream_and_wait(), ast_strlen_zero, conf_announce_channel_depart(), conf_announce_channel_push(), confbridge_conference::name, NULL, confbridge_conference::playback_chan, confbridge_conference::playback_lock, and sound_file_exists().

Referenced by action_toggle_mute_participants(), play_sound_file(), and play_sound_number().

01435 {
01436    /* Do not waste resources trying to play files that do not exist */
01437    if (!ast_strlen_zero(filename) && !sound_file_exists(filename)) {
01438       return 0;
01439    }
01440 
01441    ast_mutex_lock(&conference->playback_lock);
01442    if (!conference->playback_chan && alloc_playback_chan(conference)) {
01443       ast_mutex_unlock(&conference->playback_lock);
01444       return -1;
01445    }
01446    if (conf_announce_channel_push(conference->playback_chan)) {
01447       ast_mutex_unlock(&conference->playback_lock);
01448       return -1;
01449    }
01450 
01451    /* The channel is all under our control, in goes the prompt */
01452    if (!ast_strlen_zero(filename)) {
01453       ast_stream_and_wait(conference->playback_chan, filename, "");
01454    } else if (say_number >= 0) {
01455       ast_say_number(conference->playback_chan, say_number, "",
01456          ast_channel_language(conference->playback_chan), NULL);
01457    }
01458 
01459    ast_debug(1, "Departing announcer channel '%s' from conference bridge '%s'\n",
01460       ast_channel_name(conference->playback_chan), conference->name);
01461    conf_announce_channel_depart(conference->playback_chan);
01462 
01463    ast_mutex_unlock(&conference->playback_lock);
01464 
01465    return 0;
01466 }

static int play_sound_number ( struct confbridge_conference conference,
int  say_number 
) [static]

Play number into the conference bridge.

Parameters:
conference The conference bridge to say the number into
say_number number to say
Return values:
0 success
-1 failure

Definition at line 1482 of file app_confbridge.c.

References NULL, and play_sound_helper().

Referenced by announce_user_count().

01483 {
01484    return play_sound_helper(conference, NULL, say_number);
01485 }

static int register_channel_tech ( struct ast_channel_tech tech  )  [static]

Definition at line 3311 of file app_confbridge.c.

References ast_channel_register(), ast_format_cap_alloc, ast_format_cap_append_by_type(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_log, AST_MEDIA_TYPE_UNKNOWN, ast_channel_tech::capabilities, ast_channel_tech::description, LOG_ERROR, and ast_channel_tech::type.

Referenced by load_module().

03312 {
03313    tech->capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
03314    if (!tech->capabilities) {
03315       return -1;
03316    }
03317    ast_format_cap_append_by_type(tech->capabilities, AST_MEDIA_TYPE_UNKNOWN);
03318    if (ast_channel_register(tech)) {
03319       ast_log(LOG_ERROR, "Unable to register channel technology %s(%s).\n",
03320          tech->type, tech->description);
03321       return -1;
03322    }
03323    return 0;
03324 }

static int reload ( void   )  [static]

Definition at line 3423 of file app_confbridge.c.

References conf_reload_config().

03424 {
03425    return conf_reload_config();
03426 }

static void send_conf_end_event ( struct confbridge_conference conference  )  [static]

Definition at line 483 of file app_confbridge.c.

References confbridge_end_type(), NULL, and send_conf_stasis().

Referenced by conf_ended().

00484 {
00485    send_conf_stasis(conference, NULL, confbridge_end_type(), NULL, 0);
00486 }

static void send_conf_start_event ( struct confbridge_conference conference  )  [static]

Definition at line 478 of file app_confbridge.c.

References confbridge_start_type(), NULL, and send_conf_stasis().

Referenced by join_conference_bridge().

00479 {
00480    send_conf_stasis(conference, NULL, confbridge_start_type(), NULL, 0);
00481 }

static void send_conf_stasis ( struct confbridge_conference conference,
struct ast_channel chan,
struct stasis_message_type type,
struct ast_json extras,
int  channel_topic 
) [static]

Definition at line 445 of file app_confbridge.c.

References ao2_cleanup, ast_bridge_blob_create(), ast_bridge_lock, ast_bridge_topic(), ast_bridge_unlock, ast_channel_topic(), ast_json_object_update(), ast_json_pack(), ast_json_unref(), confbridge_conference::bridge, confbridge_conference::name, NULL, RAII_VAR, and stasis_publish().

Referenced by conf_handle_talker_cb(), send_conf_end_event(), send_conf_start_event(), send_join_event(), send_leave_event(), send_mute_event(), send_start_record_event(), send_stop_record_event(), and send_unmute_event().

00447 {
00448    RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
00449    RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
00450 
00451    json_object = ast_json_pack("{s: s}",
00452       "conference", conference->name);
00453    if (!json_object) {
00454       return;
00455    }
00456 
00457    if (extras) {
00458       ast_json_object_update(json_object, extras);
00459    }
00460 
00461    ast_bridge_lock(conference->bridge);
00462    msg = ast_bridge_blob_create(type,
00463       conference->bridge,
00464       chan,
00465       json_object);
00466    ast_bridge_unlock(conference->bridge);
00467    if (!msg) {
00468       return;
00469    }
00470 
00471    if (channel_topic) {
00472       stasis_publish(ast_channel_topic(chan), msg);
00473    } else {
00474       stasis_publish(ast_bridge_topic(conference->bridge), msg);
00475    }
00476 }

static void send_join_event ( struct confbridge_user user,
struct confbridge_conference conference 
) [static]

Definition at line 488 of file app_confbridge.c.

References ast_json_pack(), ast_json_unref(), ast_test_flag, confbridge_user::chan, confbridge_join_type(), send_conf_stasis(), confbridge_user::u_profile, and USER_OPT_ADMIN.

Referenced by confbridge_exec().

00489 {
00490    struct ast_json *json_object;
00491 
00492    json_object = ast_json_pack("{s: b}",
00493       "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
00494    );
00495    if (!json_object) {
00496       return;
00497    }
00498    send_conf_stasis(conference, user->chan, confbridge_join_type(), json_object, 0);
00499    ast_json_unref(json_object);
00500 }

static void send_leave_event ( struct confbridge_user user,
struct confbridge_conference conference 
) [static]

Definition at line 502 of file app_confbridge.c.

References ast_json_pack(), ast_json_unref(), ast_test_flag, confbridge_user::chan, confbridge_leave_type(), send_conf_stasis(), confbridge_user::u_profile, and USER_OPT_ADMIN.

Referenced by confbridge_exec().

00503 {
00504    struct ast_json *json_object;
00505 
00506    json_object = ast_json_pack("{s: b}",
00507       "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
00508    );
00509    if (!json_object) {
00510       return;
00511    }
00512    send_conf_stasis(conference, user->chan, confbridge_leave_type(), json_object, 0);
00513    ast_json_unref(json_object);
00514 }

static void send_mute_event ( struct confbridge_user user,
struct confbridge_conference conference 
) [static]

Definition at line 526 of file app_confbridge.c.

References ast_json_pack(), ast_json_unref(), ast_test_flag, confbridge_user::chan, confbridge_mute_type(), send_conf_stasis(), confbridge_user::u_profile, and USER_OPT_ADMIN.

Referenced by action_toggle_mute(), and generic_mute_unmute_user().

00527 {
00528    struct ast_json *json_object;
00529 
00530    json_object = ast_json_pack("{s: b}",
00531       "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
00532    );
00533    if (!json_object) {
00534       return;
00535    }
00536    send_conf_stasis(conference, user->chan, confbridge_mute_type(), json_object, 1);
00537    ast_json_unref(json_object);
00538 }

static void send_start_record_event ( struct confbridge_conference conference  )  [static]

Definition at line 516 of file app_confbridge.c.

References confbridge_start_record_type(), NULL, and send_conf_stasis().

Referenced by conf_start_record().

00517 {
00518    send_conf_stasis(conference, NULL, confbridge_start_record_type(), NULL, 0);
00519 }

static void send_stop_record_event ( struct confbridge_conference conference  )  [static]

Definition at line 521 of file app_confbridge.c.

References confbridge_stop_record_type(), NULL, and send_conf_stasis().

Referenced by conf_stop_record().

00522 {
00523    send_conf_stasis(conference, NULL, confbridge_stop_record_type(), NULL, 0);
00524 }

static void send_unmute_event ( struct confbridge_user user,
struct confbridge_conference conference 
) [static]

Definition at line 540 of file app_confbridge.c.

References ast_json_pack(), ast_json_unref(), ast_test_flag, confbridge_user::chan, confbridge_unmute_type(), send_conf_stasis(), confbridge_user::u_profile, and USER_OPT_ADMIN.

Referenced by action_toggle_mute(), and generic_mute_unmute_user().

00541 {
00542    struct ast_json *json_object;
00543 
00544    json_object = ast_json_pack("{s: b}",
00545       "admin", ast_test_flag(&user->u_profile, USER_OPT_ADMIN)
00546    );
00547    if (!json_object) {
00548       return;
00549    }
00550    send_conf_stasis(conference, user->chan, confbridge_unmute_type(), json_object, 1);
00551    ast_json_unref(json_object);
00552 }

static void set_rec_filename ( struct confbridge_conference conference,
struct ast_str **  filename,
int  is_new 
) [static]

Definition at line 554 of file app_confbridge.c.

References ast_str_append(), ast_str_reset(), ast_str_set(), ast_str_set_substr(), ast_str_strlen(), ast_strlen_zero, ast_test_flag, confbridge_conference::b_profile, BRIDGE_OPT_RECORD_FILE_APPEND, BRIDGE_OPT_RECORD_FILE_TIMESTAMP, ext, confbridge_conference::name, bridge_profile::rec_command, bridge_profile::rec_file, and bridge_profile::rec_options.

Referenced by conf_start_record().

00555 {
00556    char *rec_file = conference->b_profile.rec_file;
00557    char *ext;
00558    time_t now;
00559 
00560    if (ast_str_strlen(*filename)
00561       && ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_APPEND)
00562       && !is_new) {
00563       return;
00564    }
00565 
00566    time(&now);
00567 
00568    ast_str_reset(*filename);
00569    if (ast_strlen_zero(rec_file)) {
00570       ast_str_set(filename, 0, "confbridge-%s-%u.wav", conference->name,
00571          (unsigned int) now);
00572    } else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_TIMESTAMP)) {
00573       /* insert time before file extension */
00574       ext = strrchr(rec_file, '.');
00575       if (ext) {
00576          ast_str_set_substr(filename, 0, rec_file, ext - rec_file);
00577          ast_str_append(filename, 0, "-%u%s", (unsigned int) now, ext);
00578       } else {
00579          ast_str_set(filename, 0, "%s-%u", rec_file, (unsigned int) now);
00580       }
00581    } else {
00582       ast_str_set(filename, 0, "%s", rec_file);
00583    }
00584    ast_str_append(filename, 0, ",%s%s,%s",
00585       ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_FILE_APPEND) ? "a" : "",
00586       conference->b_profile.rec_options,
00587       conference->b_profile.rec_command);
00588 }

static int sound_file_exists ( const char *  filename  )  [static]

Definition at line 780 of file app_confbridge.c.

References ast_fileexists(), ast_log, LOG_WARNING, and NULL.

Referenced by announce_user_count(), and play_sound_helper().

00781 {
00782    if (ast_fileexists(filename, NULL, NULL)) {
00783       return -1;
00784    }
00785    ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
00786    return 0;
00787 }

static int unload_module ( void   )  [static]

Called when module is being unloaded.

Definition at line 3327 of file app_confbridge.c.

References ao2_cleanup, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_manager_unregister(), ast_unregister_application(), conf_announce_get_tech(), conf_destroy_config(), conf_record_get_tech(), manager_confbridge_shutdown(), NULL, and unregister_channel_tech().

03328 {
03329    ast_unregister_application(app);
03330 
03331    ast_custom_function_unregister(&confbridge_function);
03332    ast_custom_function_unregister(&confbridge_info_function);
03333 
03334    ast_cli_unregister_multiple(cli_confbridge, ARRAY_LEN(cli_confbridge));
03335 
03336    ast_manager_unregister("ConfbridgeList");
03337    ast_manager_unregister("ConfbridgeListRooms");
03338    ast_manager_unregister("ConfbridgeMute");
03339    ast_manager_unregister("ConfbridgeUnmute");
03340    ast_manager_unregister("ConfbridgeKick");
03341    ast_manager_unregister("ConfbridgeUnlock");
03342    ast_manager_unregister("ConfbridgeLock");
03343    ast_manager_unregister("ConfbridgeStartRecord");
03344    ast_manager_unregister("ConfbridgeStopRecord");
03345    ast_manager_unregister("ConfbridgeSetSingleVideoSrc");
03346 
03347    /* Unsubscribe from stasis confbridge message type and clean it up. */
03348    manager_confbridge_shutdown();
03349 
03350    /* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */
03351    ao2_cleanup(conference_bridges);
03352    conference_bridges = NULL;
03353 
03354    conf_destroy_config();
03355 
03356    unregister_channel_tech(conf_announce_get_tech());
03357    unregister_channel_tech(conf_record_get_tech());
03358 
03359    return 0;
03360 }

static void unregister_channel_tech ( struct ast_channel_tech tech  )  [static]

Definition at line 3295 of file app_confbridge.c.

References ao2_cleanup, ast_channel_unregister(), and ast_channel_tech::capabilities.

Referenced by unload_module().

03296 {
03297    ast_channel_unregister(tech);
03298    ao2_cleanup(tech->capabilities);
03299 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Conference Bridge Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, } [static]

Definition at line 3434 of file app_confbridge.c.

const char app[] = "ConfBridge" [static]

Playing back a file to a channel in a conference
You might notice in this application that while playing a sound file to a channel the actual conference bridge lock is not held. This is done so that other channels are not blocked from interacting with the conference bridge. Unfortunately because of this it is possible for things to change after the sound file is done being played. Data must therefore be checked after reacquiring the conference bridge lock if it is important.

Definition at line 325 of file app_confbridge.c.

Definition at line 3434 of file app_confbridge.c.

struct ast_cli_entry cli_confbridge[] [static]

Definition at line 2799 of file app_confbridge.c.

Initial value:

 {
   .name = "CONFBRIDGE",
   .write = func_confbridge_helper,
}

Definition at line 2809 of file app_confbridge.c.

Initial value:

 {
   .name = "CONFBRIDGE_INFO",
   .read = func_confbridge_info,
}

Definition at line 2815 of file app_confbridge.c.

Container to hold all conference bridges in progress.

Definition at line 334 of file app_confbridge.c.

Referenced by announce_request().


Generated on Thu Apr 16 06:28:22 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6