#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/bridging.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"

Go to the source code of this file.
Defines | |
| #define | CONFERENCE_BRIDGE_BUCKETS 53 |
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 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 conference_bridge *conference_bridge, struct ast_bridge_channel *bridge_channel, struct conference_bridge_user *conference_bridge_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 conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_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 conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user, struct ast_channel *chan) |
| static int | action_toggle_mute_participants (struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) |
| static int | alloc_playback_chan (struct conference_bridge *conference_bridge) |
| static int | announce_user_count (struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) |
| 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 int | conf_get_pin (struct ast_channel *chan, struct conference_bridge_user *conference_bridge_user) |
| const char * | conf_get_sound (enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds) |
| int | conf_handle_dtmf (struct ast_bridge_channel *bridge_channel, struct conference_bridge_user *conference_bridge_user, struct conf_menu_entry *menu_entry, struct conf_menu *menu) |
| static void | conf_handle_talker_cb (struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *pvt_data) |
| static void | conf_handle_talker_destructor (void *pvt_data) |
| static int | conf_is_recording (struct conference_bridge *conference_bridge) |
| static int | conf_rec_name (struct conference_bridge_user *user, const char *conf_name) |
| static int | conf_start_record (struct conference_bridge *conference_bridge) |
| static int | conf_stop_record (struct conference_bridge *conference_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 conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_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) |
| static int | generic_mute_unmute_helper (int mute, const char *conference, const char *user) |
| 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 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 void | handle_video_on_exit (struct conference_bridge *conference_bridge, struct ast_channel *chan) |
| static void | handle_video_on_join (struct conference_bridge *conference_bridge, struct ast_channel *chan, int marked) |
| static struct conference_bridge * | join_conference_bridge (const char *name, struct conference_bridge_user *conference_bridge_user) |
| Join a conference bridge. | |
| static void | leave_conference_bridge (struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) |
| Leave a conference bridge. | |
| static int | load_module (void) |
| Called when module is being loaded. | |
| static int | play_prompt_to_channel (struct conference_bridge *conference_bridge, struct ast_channel *chan, const char *file) |
| Play back an audio file to a channel. | |
| static int | play_sound_file (struct conference_bridge *conference_bridge, const char *filename) |
| Play sound file into conference bridge. | |
| static int | play_sound_helper (struct conference_bridge *conference_bridge, const char *filename, int say_number) |
| static int | play_sound_number (struct conference_bridge *conference_bridge, int say_number) |
| Play number into the conference bridge. | |
| static int | post_join_marked (struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) |
| Perform post-joining marked specific actions. | |
| static int | post_join_unmarked (struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user) |
| Perform post-joining non-marked specific actions. | |
| static struct ast_frame * | rec_read (struct ast_channel *ast) |
| static struct ast_channel * | rec_request (const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause) |
| static int | rec_write (struct ast_channel *ast, struct ast_frame *f) |
| static void * | record_thread (void *obj) |
| static int | reload (void) |
| static void | send_conf_end_event (const char *conf_name) |
| static void | send_conf_start_event (const char *conf_name) |
| static void | send_join_event (struct ast_channel *chan, const char *conf_name) |
| static void | send_leave_event (struct ast_channel *chan, const char *conf_name) |
| static int | unload_module (void) |
| Called when module is being unloaded. | |
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, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, } |
| static const char | app [] = "ConfBridge" |
| static struct ast_module_info * | ast_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 |
| static struct ao2_container * | conference_bridges |
| Container to hold all conference bridges in progress. | |
| static struct ast_channel_tech | record_tech |
This is a conference bridge application utilizing the bridging core.
Definition in file app_confbridge.c.
| #define CONFERENCE_BRIDGE_BUCKETS 53 |
| static void __reg_module | ( | void | ) | [static] |
Definition at line 2804 of file app_confbridge.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 2804 of file app_confbridge.c.
| static int action_confbridgekick | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2487 of file app_confbridge.c.
References ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_bridge_remove(), ast_channel_name(), ast_copy_string(), AST_LIST_TRAVERSE, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and OBJ_POINTER.
Referenced by load_module().
02488 { 02489 const char *conference = astman_get_header(m, "Conference"); 02490 const char *channel = astman_get_header(m, "Channel"); 02491 struct conference_bridge_user *participant = NULL; 02492 struct conference_bridge *bridge = NULL; 02493 struct conference_bridge tmp; 02494 int found = 0; 02495 02496 if (ast_strlen_zero(conference)) { 02497 astman_send_error(s, m, "No Conference name provided."); 02498 return 0; 02499 } 02500 if (!ao2_container_count(conference_bridges)) { 02501 astman_send_error(s, m, "No active conferences."); 02502 return 0; 02503 } 02504 ast_copy_string(tmp.name, conference, sizeof(tmp.name)); 02505 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 02506 if (!bridge) { 02507 astman_send_error(s, m, "No Conference by that name found."); 02508 return 0; 02509 } 02510 02511 ao2_lock(bridge); 02512 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { 02513 if (!strcasecmp(ast_channel_name(participant->chan), channel)) { 02514 participant->kicked = 1; 02515 ast_bridge_remove(bridge->bridge, participant->chan); 02516 found = 1; 02517 break; 02518 } 02519 } 02520 ao2_unlock(bridge); 02521 ao2_ref(bridge, -1); 02522 02523 if (found) { 02524 astman_send_ack(s, m, "User kicked"); 02525 } else { 02526 astman_send_error(s, m, "No Channel by that name found in Conference."); 02527 } 02528 return 0; 02529 }
| static int action_confbridgelist | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2298 of file app_confbridge.c.
References ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_channel_name(), ast_copy_string(), AST_LIST_TRAVERSE, ast_strlen_zero(), ast_test_flag, astman_append(), astman_get_header(), astman_send_error(), astman_send_listack(), OBJ_POINTER, S_COR, and total.
Referenced by load_module().
02299 { 02300 const char *actionid = astman_get_header(m, "ActionID"); 02301 const char *conference = astman_get_header(m, "Conference"); 02302 struct conference_bridge_user *participant = NULL; 02303 struct conference_bridge *bridge = NULL; 02304 struct conference_bridge tmp; 02305 char id_text[80] = ""; 02306 int total = 0; 02307 02308 if (!ast_strlen_zero(actionid)) { 02309 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid); 02310 } 02311 if (ast_strlen_zero(conference)) { 02312 astman_send_error(s, m, "No Conference name provided."); 02313 return 0; 02314 } 02315 if (!ao2_container_count(conference_bridges)) { 02316 astman_send_error(s, m, "No active conferences."); 02317 return 0; 02318 } 02319 ast_copy_string(tmp.name, conference, sizeof(tmp.name)); 02320 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 02321 if (!bridge) { 02322 astman_send_error(s, m, "No Conference by that name found."); 02323 return 0; 02324 } 02325 02326 astman_send_listack(s, m, "Confbridge user list will follow", "start"); 02327 02328 ao2_lock(bridge); 02329 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { 02330 total++; 02331 astman_append(s, 02332 "Event: ConfbridgeList\r\n" 02333 "%s" 02334 "Conference: %s\r\n" 02335 "CallerIDNum: %s\r\n" 02336 "CallerIDName: %s\r\n" 02337 "Channel: %s\r\n" 02338 "Admin: %s\r\n" 02339 "MarkedUser: %s\r\n" 02340 "\r\n", 02341 id_text, 02342 bridge->name, 02343 S_COR(participant->chan->caller.id.number.valid, participant->chan->caller.id.number.str, "<unknown>"), 02344 S_COR(participant->chan->caller.id.name.valid, participant->chan->caller.id.name.str, "<no name>"), 02345 ast_channel_name(participant->chan), 02346 ast_test_flag(&participant->u_profile, USER_OPT_ADMIN) ? "Yes" : "No", 02347 ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No"); 02348 } 02349 ao2_unlock(bridge); 02350 ao2_ref(bridge, -1); 02351 02352 astman_append(s, 02353 "Event: ConfbridgeListComplete\r\n" 02354 "EventList: Complete\r\n" 02355 "ListItems: %d\r\n" 02356 "%s" 02357 "\r\n", total, id_text); 02358 02359 return 0; 02360 }
| static int action_confbridgelistrooms | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2362 of file app_confbridge.c.
References 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(), and astman_send_listack().
Referenced by load_module().
02363 { 02364 const char *actionid = astman_get_header(m, "ActionID"); 02365 struct conference_bridge *bridge = NULL; 02366 struct ao2_iterator i; 02367 char id_text[512] = ""; 02368 int totalitems = 0; 02369 02370 if (!ast_strlen_zero(actionid)) { 02371 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", actionid); 02372 } 02373 02374 if (!ao2_container_count(conference_bridges)) { 02375 astman_send_error(s, m, "No active conferences."); 02376 return 0; 02377 } 02378 02379 astman_send_listack(s, m, "Confbridge conferences will follow", "start"); 02380 02381 /* Traverse the conference list */ 02382 i = ao2_iterator_init(conference_bridges, 0); 02383 while ((bridge = ao2_iterator_next(&i))) { 02384 totalitems++; 02385 02386 ao2_lock(bridge); 02387 astman_append(s, 02388 "Event: ConfbridgeListRooms\r\n" 02389 "%s" 02390 "Conference: %s\r\n" 02391 "Parties: %d\r\n" 02392 "Marked: %d\r\n" 02393 "Locked: %s\r\n" 02394 "\r\n", 02395 id_text, 02396 bridge->name, 02397 bridge->users, 02398 bridge->markedusers, 02399 bridge->locked ? "Yes" : "No"); 02400 ao2_unlock(bridge); 02401 02402 ao2_ref(bridge, -1); 02403 } 02404 ao2_iterator_destroy(&i); 02405 02406 /* Send final confirmation */ 02407 astman_append(s, 02408 "Event: ConfbridgeListRoomsComplete\r\n" 02409 "EventList: Complete\r\n" 02410 "ListItems: %d\r\n" 02411 "%s" 02412 "\r\n", totalitems, id_text); 02413 return 0; 02414 }
| static int action_confbridgelock | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2482 of file app_confbridge.c.
References action_lock_unlock_helper().
Referenced by load_module().
02483 { 02484 return action_lock_unlock_helper(s, m, 1); 02485 }
| static int action_confbridgemute | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2453 of file app_confbridge.c.
References action_mute_unmute_helper().
Referenced by load_module().
02454 { 02455 return action_mute_unmute_helper(s, m, 1); 02456 }
| static int action_confbridgesetsinglevideosrc | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2609 of file app_confbridge.c.
References ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_bridge_set_single_src_video_mode(), ast_channel_name(), ast_copy_string(), AST_LIST_TRAVERSE, ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and OBJ_POINTER.
Referenced by load_module().
02610 { 02611 const char *conference = astman_get_header(m, "Conference"); 02612 const char *channel = astman_get_header(m, "Channel"); 02613 struct conference_bridge_user *participant = NULL; 02614 struct conference_bridge *bridge = NULL; 02615 struct conference_bridge tmp; 02616 02617 if (ast_strlen_zero(conference)) { 02618 astman_send_error(s, m, "No Conference name provided."); 02619 return 0; 02620 } 02621 if (ast_strlen_zero(channel)) { 02622 astman_send_error(s, m, "No channel name provided."); 02623 return 0; 02624 } 02625 if (!ao2_container_count(conference_bridges)) { 02626 astman_send_error(s, m, "No active conferences."); 02627 return 0; 02628 } 02629 02630 ast_copy_string(tmp.name, conference, sizeof(tmp.name)); 02631 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 02632 if (!bridge) { 02633 astman_send_error(s, m, "No Conference by that name found."); 02634 return 0; 02635 } 02636 02637 /* find channel and set as video src. */ 02638 ao2_lock(bridge); 02639 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { 02640 if (!strncmp(channel, ast_channel_name(participant->chan), strlen(channel))) { 02641 ast_bridge_set_single_src_video_mode(bridge->bridge, participant->chan); 02642 break; 02643 } 02644 } 02645 ao2_unlock(bridge); 02646 ao2_ref(bridge, -1); 02647 02648 /* do not access participant after bridge unlock. We are just 02649 * using this check to see if it was found or not */ 02650 if (!participant) { 02651 astman_send_error(s, m, "No channel by that name found in conference."); 02652 return 0; 02653 } 02654 astman_send_ack(s, m, "Conference single video source set."); 02655 return 0; 02656 }
| static int action_confbridgestartrecord | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2531 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(), conf_is_recording(), conf_start_record(), and OBJ_POINTER.
Referenced by load_module().
02532 { 02533 const char *conference = astman_get_header(m, "Conference"); 02534 const char *recordfile = astman_get_header(m, "RecordFile"); 02535 struct conference_bridge *bridge = NULL; 02536 struct conference_bridge tmp; 02537 02538 if (ast_strlen_zero(conference)) { 02539 astman_send_error(s, m, "No Conference name provided."); 02540 return 0; 02541 } 02542 if (!ao2_container_count(conference_bridges)) { 02543 astman_send_error(s, m, "No active conferences."); 02544 return 0; 02545 } 02546 02547 ast_copy_string(tmp.name, conference, sizeof(tmp.name)); 02548 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 02549 if (!bridge) { 02550 astman_send_error(s, m, "No Conference by that name found."); 02551 return 0; 02552 } 02553 02554 if (conf_is_recording(bridge)) { 02555 astman_send_error(s, m, "Conference is already being recorded."); 02556 ao2_ref(bridge, -1); 02557 return 0; 02558 } 02559 02560 if (!ast_strlen_zero(recordfile)) { 02561 ao2_lock(bridge); 02562 ast_copy_string(bridge->b_profile.rec_file, recordfile, sizeof(bridge->b_profile.rec_file)); 02563 ao2_unlock(bridge); 02564 } 02565 02566 if (conf_start_record(bridge)) { 02567 astman_send_error(s, m, "Internal error starting conference recording."); 02568 ao2_ref(bridge, -1); 02569 return 0; 02570 } 02571 02572 ao2_ref(bridge, -1); 02573 astman_send_ack(s, m, "Conference Recording Started."); 02574 return 0; 02575 }
| static int action_confbridgestoprecord | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2576 of file app_confbridge.c.
References ao2_container_count(), ao2_find, ao2_ref, ast_copy_string(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), conf_stop_record(), and OBJ_POINTER.
Referenced by load_module().
02577 { 02578 const char *conference = astman_get_header(m, "Conference"); 02579 struct conference_bridge *bridge = NULL; 02580 struct conference_bridge tmp; 02581 02582 if (ast_strlen_zero(conference)) { 02583 astman_send_error(s, m, "No Conference name provided."); 02584 return 0; 02585 } 02586 if (!ao2_container_count(conference_bridges)) { 02587 astman_send_error(s, m, "No active conferences."); 02588 return 0; 02589 } 02590 02591 ast_copy_string(tmp.name, conference, sizeof(tmp.name)); 02592 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 02593 if (!bridge) { 02594 astman_send_error(s, m, "No Conference by that name found."); 02595 return 0; 02596 } 02597 02598 if (conf_stop_record(bridge)) { 02599 astman_send_error(s, m, "Internal error while stopping recording."); 02600 ao2_ref(bridge, -1); 02601 return 0; 02602 } 02603 02604 ao2_ref(bridge, -1); 02605 astman_send_ack(s, m, "Conference Recording Stopped."); 02606 return 0; 02607 }
| static int action_confbridgeunlock | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2478 of file app_confbridge.c.
References action_lock_unlock_helper().
Referenced by load_module().
02479 { 02480 return action_lock_unlock_helper(s, m, 0); 02481 }
| static int action_confbridgeunmute | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 2449 of file app_confbridge.c.
References action_mute_unmute_helper().
Referenced by load_module().
02450 { 02451 return action_mute_unmute_helper(s, m, 0); 02452 }
| static int action_dialplan_exec | ( | struct ast_bridge_channel * | bridge_channel, | |
| struct conf_menu_action * | menu_action | |||
| ) | [static] |
Definition at line 1709 of file app_confbridge.c.
References ast_channel_lock, ast_channel_unlock, ast_copy_string(), ast_pbx_run_args(), ast_strdupa, ast_bridge_channel::chan, ast_channel::context, context, ast_channel::exten, exten, ast_pbx_args::no_hangup_chan, ast_channel::pbx, and ast_channel::priority.
Referenced by execute_menu_entry().
01710 { 01711 struct ast_pbx_args args; 01712 struct ast_pbx *pbx; 01713 char *exten; 01714 char *context; 01715 int priority; 01716 int res; 01717 01718 memset(&args, 0, sizeof(args)); 01719 args.no_hangup_chan = 1; 01720 01721 ast_channel_lock(bridge_channel->chan); 01722 01723 /*save off*/ 01724 exten = ast_strdupa(bridge_channel->chan->exten); 01725 context = ast_strdupa(bridge_channel->chan->context); 01726 priority = bridge_channel->chan->priority; 01727 pbx = bridge_channel->chan->pbx; 01728 bridge_channel->chan->pbx = NULL; 01729 01730 /*set new*/ 01731 ast_copy_string(bridge_channel->chan->exten, menu_action->data.dialplan_args.exten, sizeof(bridge_channel->chan->exten)); 01732 ast_copy_string(bridge_channel->chan->context, menu_action->data.dialplan_args.context, sizeof(bridge_channel->chan->context)); 01733 bridge_channel->chan->priority = menu_action->data.dialplan_args.priority; 01734 01735 ast_channel_unlock(bridge_channel->chan); 01736 01737 /*execute*/ 01738 res = ast_pbx_run_args(bridge_channel->chan, &args); 01739 01740 /*restore*/ 01741 ast_channel_lock(bridge_channel->chan); 01742 01743 ast_copy_string(bridge_channel->chan->exten, exten, sizeof(bridge_channel->chan->exten)); 01744 ast_copy_string(bridge_channel->chan->context, context, sizeof(bridge_channel->chan->context)); 01745 bridge_channel->chan->priority = priority; 01746 bridge_channel->chan->pbx = pbx; 01747 01748 ast_channel_unlock(bridge_channel->chan); 01749 01750 return res; 01751 }
| static int action_kick_last | ( | struct conference_bridge * | conference_bridge, | |
| struct ast_bridge_channel * | bridge_channel, | |||
| struct conference_bridge_user * | conference_bridge_user | |||
| ) | [static] |
Definition at line 1677 of file app_confbridge.c.
References ao2_lock, ao2_unlock, ast_bridge_remove(), ast_channel_name(), AST_LIST_LAST, ast_log(), ast_stream_and_wait(), ast_test_flag, ast_bridge_channel::chan, conf_get_sound(), and LOG_WARNING.
Referenced by execute_menu_entry().
01680 { 01681 struct conference_bridge_user *last_participant = NULL; 01682 int isadmin = ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN); 01683 01684 if (!isadmin) { 01685 ast_stream_and_wait(bridge_channel->chan, 01686 conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds), 01687 ""); 01688 ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n", 01689 ast_channel_name(bridge_channel->chan), 01690 conference_bridge->name); 01691 return -1; 01692 } 01693 01694 ao2_lock(conference_bridge); 01695 if (((last_participant = AST_LIST_LAST(&conference_bridge->users_list)) == conference_bridge_user) 01696 || (ast_test_flag(&last_participant->u_profile, USER_OPT_ADMIN))) { 01697 ao2_unlock(conference_bridge); 01698 ast_stream_and_wait(bridge_channel->chan, 01699 conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds), 01700 ""); 01701 } else if (last_participant) { 01702 last_participant->kicked = 1; 01703 ast_bridge_remove(conference_bridge->bridge, last_participant->chan); 01704 ao2_unlock(conference_bridge); 01705 } 01706 return 0; 01707 }
| static int action_lock_unlock_helper | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| int | lock | |||
| ) | [static] |
Definition at line 2458 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().
02459 { 02460 const char *conference = astman_get_header(m, "Conference"); 02461 int res = 0; 02462 02463 if (ast_strlen_zero(conference)) { 02464 astman_send_error(s, m, "No Conference name provided."); 02465 return 0; 02466 } 02467 if (!ao2_container_count(conference_bridges)) { 02468 astman_send_error(s, m, "No active conferences."); 02469 return 0; 02470 } 02471 if ((res = generic_lock_unlock_helper(lock, conference))) { 02472 astman_send_error(s, m, "No Conference by that name found."); 02473 return 0; 02474 } 02475 astman_send_ack(s, m, lock ? "Conference locked" : "Conference unlocked"); 02476 return 0; 02477 }
| static int action_mute_unmute_helper | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| int | mute | |||
| ) | [static] |
Definition at line 2416 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().
02417 { 02418 const char *conference = astman_get_header(m, "Conference"); 02419 const char *channel = astman_get_header(m, "Channel"); 02420 int res = 0; 02421 02422 if (ast_strlen_zero(conference)) { 02423 astman_send_error(s, m, "No Conference name provided."); 02424 return 0; 02425 } 02426 if (ast_strlen_zero(channel)) { 02427 astman_send_error(s, m, "No channel name provided."); 02428 return 0; 02429 } 02430 if (!ao2_container_count(conference_bridges)) { 02431 astman_send_error(s, m, "No active conferences."); 02432 return 0; 02433 } 02434 02435 res = generic_mute_unmute_helper(mute, conference, channel); 02436 02437 if (res == -1) { 02438 astman_send_error(s, m, "No Conference by that name found."); 02439 return 0; 02440 } else if (res == -2) { 02441 astman_send_error(s, m, "No Channel by that name found in Conference."); 02442 return 0; 02443 } 02444 02445 astman_send_ack(s, m, mute ? "User muted" : "User unmuted"); 02446 return 0; 02447 }
| static int action_playback | ( | struct ast_bridge_channel * | bridge_channel, | |
| const char * | playback_file | |||
| ) | [static] |
Definition at line 1592 of file app_confbridge.c.
References ast_log(), ast_strdupa, ast_stream_and_wait(), ast_bridge_channel::chan, LOG_WARNING, and strsep().
Referenced by execute_menu_entry().
01593 { 01594 char *file_copy = ast_strdupa(playback_file); 01595 char *file = NULL; 01596 01597 while ((file = strsep(&file_copy, "&"))) { 01598 if (ast_stream_and_wait(bridge_channel->chan, file, "")) { 01599 ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file); 01600 return -1; 01601 } 01602 } 01603 return 0; 01604 }
| static int action_playback_and_continue | ( | struct conference_bridge * | conference_bridge, | |
| struct conference_bridge_user * | conference_bridge_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 1606 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, execute_menu_entry(), LOG_WARNING, MAXIMUM_DTMF_FEATURE_STRING, and strsep().
Referenced by execute_menu_entry().
01613 { 01614 int i; 01615 int digit = 0; 01616 char dtmf[MAXIMUM_DTMF_FEATURE_STRING]; 01617 struct conf_menu_entry new_menu_entry = { { 0, }, }; 01618 char *file_copy = ast_strdupa(playback_file); 01619 char *file = NULL; 01620 01621 while ((file = strsep(&file_copy, "&"))) { 01622 if (ast_streamfile(bridge_channel->chan, file, ast_channel_language(bridge_channel->chan))) { 01623 ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file); 01624 return -1; 01625 } 01626 01627 /* now wait for more digits. */ 01628 if (!(digit = ast_waitstream(bridge_channel->chan, AST_DIGIT_ANY))) { 01629 /* streaming finished and no DTMF was entered */ 01630 continue; 01631 } else if (digit == -1) { 01632 /* error */ 01633 return -1; 01634 } else { 01635 break; /* dtmf was entered */ 01636 } 01637 } 01638 if (!digit) { 01639 /* streaming finished on all files and no DTMF was entered */ 01640 return -1; 01641 } 01642 ast_stopstream(bridge_channel->chan); 01643 01644 /* If we get here, then DTMF has been entered, This means no 01645 * additional prompts should be played for this menu entry */ 01646 *stop_prompts = 1; 01647 01648 /* If a digit was pressed during the payback, update 01649 * the dtmf string and look for a new menu entry in the 01650 * menu structure */ 01651 ast_copy_string(dtmf, cur_dtmf, sizeof(dtmf)); 01652 for (i = 0; i < (MAXIMUM_DTMF_FEATURE_STRING - 1); i++) { 01653 dtmf[i] = cur_dtmf[i]; 01654 if (!dtmf[i]) { 01655 dtmf[i] = (char) digit; 01656 dtmf[i + 1] = '\0'; 01657 i = -1; 01658 break; 01659 } 01660 } 01661 /* If i is not -1 then the new dtmf digit was _NOT_ added to the string. 01662 * If this is the case, no new DTMF sequence should be looked for. */ 01663 if (i != -1) { 01664 return 0; 01665 } 01666 01667 if (conf_find_menu_entry_by_sequence(dtmf, menu, &new_menu_entry)) { 01668 execute_menu_entry(conference_bridge, 01669 conference_bridge_user, 01670 bridge_channel, 01671 &new_menu_entry, menu); 01672 conf_menu_entry_destroy(&new_menu_entry); 01673 } 01674 return 0; 01675 }
| static int action_toggle_mute | ( | struct conference_bridge * | conference_bridge, | |
| struct conference_bridge_user * | conference_bridge_user, | |||
| struct ast_channel * | chan | |||
| ) | [static] |
Definition at line 1546 of file app_confbridge.c.
References ast_channel_name(), ast_stream_and_wait(), ast_test_flag, ast_test_suite_event_notify, and conf_get_sound().
Referenced by execute_menu_entry().
01549 { 01550 /* Mute or unmute yourself, note we only allow manipulation if they aren't waiting for a marked user or if marked users exist */ 01551 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_WAITMARKED) || conference_bridge->markedusers) { 01552 conference_bridge_user->features.mute = (!conference_bridge_user->features.mute ? 1 : 0); 01553 ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(chan), conference_bridge_user->features.mute ? "muted" : "unmuted", conference_bridge_user->b_profile.name, ast_channel_name(chan)); 01554 } 01555 return ast_stream_and_wait(chan, (conference_bridge_user->features.mute ? 01556 conf_get_sound(CONF_SOUND_MUTED, conference_bridge_user->b_profile.sounds) : 01557 conf_get_sound(CONF_SOUND_UNMUTED, conference_bridge_user->b_profile.sounds)), 01558 ""); 01559 }
| static int action_toggle_mute_participants | ( | struct conference_bridge * | conference_bridge, | |
| struct conference_bridge_user * | conference_bridge_user | |||
| ) | [static] |
Definition at line 1561 of file app_confbridge.c.
References ao2_lock, ao2_unlock, ast_autoservice_start(), ast_autoservice_stop(), AST_LIST_TRAVERSE, ast_stream_and_wait(), ast_test_flag, conf_get_sound(), and play_sound_helper().
Referenced by execute_menu_entry().
01562 { 01563 struct conference_bridge_user *participant = NULL; 01564 const char *sound_to_play; 01565 01566 ao2_lock(conference_bridge); 01567 01568 /* If already muted, then unmute */ 01569 conference_bridge->muted = conference_bridge->muted ? 0 : 1; 01570 sound_to_play = conf_get_sound((conference_bridge->muted ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED), 01571 conference_bridge_user->b_profile.sounds); 01572 01573 AST_LIST_TRAVERSE(&conference_bridge->users_list, participant, list) { 01574 if (!ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) { 01575 participant->features.mute = conference_bridge->muted; 01576 } 01577 } 01578 01579 ao2_unlock(conference_bridge); 01580 01581 /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */ 01582 ast_stream_and_wait(conference_bridge_user->chan, sound_to_play, ""); 01583 01584 /* Announce to the group that all participants are muted */ 01585 ast_autoservice_start(conference_bridge_user->chan); 01586 play_sound_helper(conference_bridge, sound_to_play, 0); 01587 ast_autoservice_stop(conference_bridge_user->chan); 01588 01589 return 0; 01590 }
| static int alloc_playback_chan | ( | struct conference_bridge * | conference_bridge | ) | [static] |
Definition at line 1115 of file app_confbridge.c.
References ast_call(), ast_debug, ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_set(), AST_FORMAT_SLINEAR, ast_hangup(), ast_request(), and cause.
Referenced by play_sound_helper().
01116 { 01117 int cause; 01118 struct ast_format_cap *cap; 01119 struct ast_format tmpfmt; 01120 01121 if (conference_bridge->playback_chan) { 01122 return 0; 01123 } 01124 if (!(cap = ast_format_cap_alloc_nolock())) { 01125 return -1; 01126 } 01127 ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); 01128 if (!(conference_bridge->playback_chan = ast_request("Bridge", cap, NULL, "", &cause))) { 01129 cap = ast_format_cap_destroy(cap); 01130 return -1; 01131 } 01132 cap = ast_format_cap_destroy(cap); 01133 01134 conference_bridge->playback_chan->bridge = conference_bridge->bridge; 01135 01136 if (ast_call(conference_bridge->playback_chan, "", 0)) { 01137 ast_hangup(conference_bridge->playback_chan); 01138 conference_bridge->playback_chan = NULL; 01139 return -1; 01140 } 01141 01142 ast_debug(1, "Created a playback channel to conference bridge '%s'\n", conference_bridge->name); 01143 return 0; 01144 }
| static int announce_user_count | ( | struct conference_bridge * | conference_bridge, | |
| struct conference_bridge_user * | conference_bridge_user | |||
| ) | [static] |
Announce number of users in the conference bridge to the caller.
| conference_bridge | Conference bridge to peek at | |
| (OPTIONAL) | conference_bridge_user Caller |
Definition at line 581 of file app_confbridge.c.
References ast_channel_language(), ast_say_number(), ast_stream_and_wait(), conf_get_sound(), play_sound_file(), and play_sound_number().
Referenced by execute_menu_entry(), and post_join_unmarked().
00582 { 00583 const char *other_in_party = conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, conference_bridge->b_profile.sounds); 00584 const char *only_one = conf_get_sound(CONF_SOUND_ONLY_ONE, conference_bridge->b_profile.sounds); 00585 const char *there_are = conf_get_sound(CONF_SOUND_THERE_ARE, conference_bridge->b_profile.sounds); 00586 00587 if (conference_bridge->users == 1) { 00588 /* Awww we are the only person in the conference bridge */ 00589 return 0; 00590 } else if (conference_bridge->users == 2) { 00591 if (conference_bridge_user) { 00592 /* Eep, there is one other person */ 00593 if (ast_stream_and_wait(conference_bridge_user->chan, 00594 only_one, 00595 "")) { 00596 return -1; 00597 } 00598 } else { 00599 play_sound_file(conference_bridge, only_one); 00600 } 00601 } else { 00602 /* Alas multiple others in here */ 00603 if (conference_bridge_user) { 00604 if (ast_stream_and_wait(conference_bridge_user->chan, 00605 there_are, 00606 "")) { 00607 return -1; 00608 } 00609 if (ast_say_number(conference_bridge_user->chan, conference_bridge->users - 1, "", ast_channel_language(conference_bridge_user->chan), NULL)) { 00610 return -1; 00611 } 00612 if (ast_stream_and_wait(conference_bridge_user->chan, 00613 other_in_party, 00614 "")) { 00615 return -1; 00616 } 00617 } else { 00618 play_sound_file(conference_bridge, there_are); 00619 play_sound_number(conference_bridge, conference_bridge->users - 1); 00620 play_sound_file(conference_bridge, other_in_party); 00621 } 00622 } 00623 return 0; 00624 }
| static int cli_mute_unmute_helper | ( | int | mute, | |
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2078 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().
02079 { 02080 int res = generic_mute_unmute_helper(mute, a->argv[2], a->argv[3]); 02081 02082 if (res == -1) { 02083 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]); 02084 return -1; 02085 } else if (res == -2) { 02086 ast_cli(a->fd, "No channel named '%s' found in conference %s\n", a->argv[3], a->argv[2]); 02087 return -1; 02088 } 02089 ast_cli(a->fd, "%s %s from confbridge %s\n", mute ? "Muting" : "Unmuting", a->argv[3], a->argv[2]); 02090 return 0; 02091 }
| static char* complete_confbridge_name | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 1884 of file app_confbridge.c.
References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, and ast_strdup.
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().
01885 { 01886 int which = 0; 01887 struct conference_bridge *bridge = NULL; 01888 char *res = NULL; 01889 int wordlen = strlen(word); 01890 struct ao2_iterator i; 01891 01892 i = ao2_iterator_init(conference_bridges, 0); 01893 while ((bridge = ao2_iterator_next(&i))) { 01894 if (!strncasecmp(bridge->name, word, wordlen) && ++which > state) { 01895 res = ast_strdup(bridge->name); 01896 ao2_ref(bridge, -1); 01897 break; 01898 } 01899 ao2_ref(bridge, -1); 01900 } 01901 ao2_iterator_destroy(&i); 01902 01903 return res; 01904 }
| static int conf_get_pin | ( | struct ast_channel * | chan, | |
| struct conference_bridge_user * | conference_bridge_user | |||
| ) | [static] |
Definition at line 1236 of file app_confbridge.c.
References ast_app_getdata(), ast_channel_language(), AST_DIGIT_ANY, ast_streamfile(), ast_waitstream(), conf_get_sound(), len(), and MAX_PIN.
Referenced by confbridge_exec().
01237 { 01238 char pin_guess[MAX_PIN+1] = { 0, }; 01239 const char *pin = conference_bridge_user->u_profile.pin; 01240 char *tmp = pin_guess; 01241 int i, res; 01242 unsigned int len = MAX_PIN ; 01243 01244 /* give them three tries to get the pin right */ 01245 for (i = 0; i < 3; i++) { 01246 if (ast_app_getdata(chan, 01247 conf_get_sound(CONF_SOUND_GET_PIN, conference_bridge_user->b_profile.sounds), 01248 tmp, len, 0) >= 0) { 01249 if (!strcasecmp(pin, pin_guess)) { 01250 return 0; 01251 } 01252 } 01253 ast_streamfile(chan, 01254 conf_get_sound(CONF_SOUND_INVALID_PIN, conference_bridge_user->b_profile.sounds), 01255 ast_channel_language(chan)); 01256 res = ast_waitstream(chan, AST_DIGIT_ANY); 01257 if (res > 0) { 01258 /* Account for digit already read during ivalid pin playback 01259 * resetting pin buf. */ 01260 pin_guess[0] = res; 01261 pin_guess[1] = '\0'; 01262 tmp = pin_guess + 1; 01263 len = MAX_PIN - 1; 01264 } else { 01265 /* reset pin buf as empty buffer. */ 01266 tmp = pin_guess; 01267 len = MAX_PIN; 01268 } 01269 } 01270 return -1; 01271 }
| const char* conf_get_sound | ( | enum conf_sounds | sound, | |
| struct bridge_profile_sounds * | custom_sounds | |||
| ) |
Definition at line 301 of file app_confbridge.c.
References S_OR.
Referenced by action_kick_last(), action_toggle_mute(), action_toggle_mute_participants(), announce_user_count(), conf_get_pin(), confbridge_exec(), execute_menu_entry(), join_conference_bridge(), leave_conference_bridge(), post_join_marked(), and post_join_unmarked().
00302 { 00303 switch (sound) { 00304 case CONF_SOUND_HAS_JOINED: 00305 return S_OR(custom_sounds->hasjoin, "conf-hasjoin"); 00306 case CONF_SOUND_HAS_LEFT: 00307 return S_OR(custom_sounds->hasleft, "conf-hasleft"); 00308 case CONF_SOUND_KICKED: 00309 return S_OR(custom_sounds->kicked, "conf-kicked"); 00310 case CONF_SOUND_MUTED: 00311 return S_OR(custom_sounds->muted, "conf-muted"); 00312 case CONF_SOUND_UNMUTED: 00313 return S_OR(custom_sounds->unmuted, "conf-unmuted"); 00314 case CONF_SOUND_ONLY_ONE: 00315 return S_OR(custom_sounds->onlyone, "conf-onlyone"); 00316 case CONF_SOUND_THERE_ARE: 00317 return S_OR(custom_sounds->thereare, "conf-thereare"); 00318 case CONF_SOUND_OTHER_IN_PARTY: 00319 return S_OR(custom_sounds->otherinparty, "conf-otherinparty"); 00320 case CONF_SOUND_PLACE_IN_CONF: 00321 return S_OR(custom_sounds->placeintoconf, "conf-placeintoconf"); 00322 case CONF_SOUND_WAIT_FOR_LEADER: 00323 return S_OR(custom_sounds->waitforleader, "conf-waitforleader"); 00324 case CONF_SOUND_LEADER_HAS_LEFT: 00325 return S_OR(custom_sounds->leaderhasleft, "conf-leaderhasleft"); 00326 case CONF_SOUND_GET_PIN: 00327 return S_OR(custom_sounds->getpin, "conf-getpin"); 00328 case CONF_SOUND_INVALID_PIN: 00329 return S_OR(custom_sounds->invalidpin, "conf-invalidpin"); 00330 case CONF_SOUND_ONLY_PERSON: 00331 return S_OR(custom_sounds->onlyperson, "conf-onlyperson"); 00332 case CONF_SOUND_LOCKED: 00333 return S_OR(custom_sounds->locked, "conf-locked"); 00334 case CONF_SOUND_LOCKED_NOW: 00335 return S_OR(custom_sounds->lockednow, "conf-lockednow"); 00336 case CONF_SOUND_UNLOCKED_NOW: 00337 return S_OR(custom_sounds->unlockednow, "conf-unlockednow"); 00338 case CONF_SOUND_ERROR_MENU: 00339 return S_OR(custom_sounds->errormenu, "conf-errormenu"); 00340 case CONF_SOUND_JOIN: 00341 return S_OR(custom_sounds->join, "confbridge-join"); 00342 case CONF_SOUND_LEAVE: 00343 return S_OR(custom_sounds->leave, "confbridge-leave"); 00344 case CONF_SOUND_PARTICIPANTS_MUTED: 00345 return S_OR(custom_sounds->participantsmuted, "conf-now-muted"); 00346 case CONF_SOUND_PARTICIPANTS_UNMUTED: 00347 return S_OR(custom_sounds->participantsunmuted, "conf-now-unmuted"); 00348 } 00349 00350 return ""; 00351 }
| int conf_handle_dtmf | ( | struct ast_bridge_channel * | bridge_channel, | |
| struct conference_bridge_user * | conference_bridge_user, | |||
| struct conf_menu_entry * | menu_entry, | |||
| struct conf_menu * | menu | |||
| ) |
Definition at line 1856 of file app_confbridge.c.
References ao2_lock, ao2_unlock, ast_moh_start(), ast_moh_stop(), ast_bridge_channel::chan, and execute_menu_entry().
01860 { 01861 struct conference_bridge *conference_bridge = conference_bridge_user->conference_bridge; 01862 01863 /* See if music on hold is playing */ 01864 ao2_lock(conference_bridge); 01865 if (conference_bridge_user->playing_moh) { 01866 /* MOH is going, let's stop it */ 01867 ast_moh_stop(bridge_channel->chan); 01868 } 01869 ao2_unlock(conference_bridge); 01870 01871 /* execute the list of actions associated with this menu entry */ 01872 execute_menu_entry(conference_bridge, conference_bridge_user, bridge_channel, menu_entry, menu); 01873 01874 /* See if music on hold needs to be started back up again */ 01875 ao2_lock(conference_bridge); 01876 if (conference_bridge_user->playing_moh) { 01877 ast_moh_start(bridge_channel->chan, conference_bridge_user->u_profile.moh_class, NULL); 01878 } 01879 ao2_unlock(conference_bridge); 01880 01881 return 0; 01882 }
| static void conf_handle_talker_cb | ( | struct ast_bridge * | bridge, | |
| struct ast_bridge_channel * | bridge_channel, | |||
| void * | pvt_data | |||
| ) | [static] |
Definition at line 1211 of file app_confbridge.c.
References AST_BRIDGE_CHANNEL_STATE_START_TALKING, AST_BRIDGE_CHANNEL_STATE_STOP_TALKING, ast_channel_name(), ast_channel_uniqueid(), ast_manager_event, ast_bridge_channel::chan, EVENT_FLAG_CALL, and ast_bridge_channel::state.
Referenced by confbridge_exec().
01212 { 01213 char *conf_name = pvt_data; 01214 int talking; 01215 01216 switch (bridge_channel->state) { 01217 case AST_BRIDGE_CHANNEL_STATE_START_TALKING: 01218 talking = 1; 01219 break; 01220 case AST_BRIDGE_CHANNEL_STATE_STOP_TALKING: 01221 talking = 0; 01222 break; 01223 default: 01224 return; /* uhh this shouldn't happen, but bail if it does. */ 01225 } 01226 01227 /* notify AMI someone is has either started or stopped talking */ 01228 ast_manager_event(bridge_channel->chan, EVENT_FLAG_CALL, "ConfbridgeTalking", 01229 "Channel: %s\r\n" 01230 "Uniqueid: %s\r\n" 01231 "Conference: %s\r\n" 01232 "TalkingStatus: %s\r\n", 01233 ast_channel_name(bridge_channel->chan), ast_channel_uniqueid(bridge_channel->chan), conf_name, talking ? "on" : "off"); 01234 }
| static void conf_handle_talker_destructor | ( | void * | pvt_data | ) | [static] |
Definition at line 1206 of file app_confbridge.c.
References ast_free.
Referenced by confbridge_exec().
01207 { 01208 ast_free(pvt_data); 01209 }
| static int conf_is_recording | ( | struct conference_bridge * | conference_bridge | ) | [static] |
Definition at line 441 of file app_confbridge.c.
References ao2_lock, ao2_unlock, and AST_PTHREADT_NULL.
Referenced by action_confbridgestartrecord(), handle_cli_confbridge_start_record(), and join_conference_bridge().
00442 { 00443 int res = 0; 00444 ao2_lock(conference_bridge); 00445 if (conference_bridge->record_chan || conference_bridge->record_thread != AST_PTHREADT_NULL) { 00446 res = 1; 00447 } 00448 ao2_unlock(conference_bridge); 00449 return res; 00450 }
| static int conf_rec_name | ( | struct conference_bridge_user * | user, | |
| const char * | conf_name | |||
| ) | [static] |
Definition at line 1273 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(), errno, LOG_WARNING, and THRESHOLD_SILENCE.
Referenced by confbridge_exec().
01274 { 01275 char destdir[PATH_MAX]; 01276 int res; 01277 int duration = 20; 01278 01279 snprintf(destdir, sizeof(destdir), "%s/confbridge", ast_config_AST_SPOOL_DIR); 01280 01281 if (ast_mkdir(destdir, 0777) != 0) { 01282 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", destdir, strerror(errno)); 01283 return -1; 01284 } 01285 snprintf(user->name_rec_location, sizeof(user->name_rec_location), 01286 "%s/confbridge-name-%s-%s", destdir, 01287 conf_name, ast_channel_uniqueid(user->chan)); 01288 01289 res = ast_play_and_record(user->chan, 01290 "vm-rec-name", 01291 user->name_rec_location, 01292 10, 01293 "sln", 01294 &duration, 01295 NULL, 01296 ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE), 01297 0, 01298 NULL); 01299 01300 if (res == -1) { 01301 user->name_rec_location[0] = '\0'; 01302 return -1; 01303 } 01304 return 0; 01305 }
| static int conf_start_record | ( | struct conference_bridge * | conference_bridge | ) | [static] |
Definition at line 486 of file app_confbridge.c.
References ao2_lock, ao2_ref, ao2_unlock, ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_cap_destroy(), ast_format_set(), AST_FORMAT_SLINEAR, ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, ast_request(), ast_test_suite_event_notify, cause, LOG_WARNING, pbx_findapp(), and record_thread().
Referenced by action_confbridgestartrecord(), handle_cli_confbridge_start_record(), and join_conference_bridge().
00487 { 00488 struct ast_format_cap *cap = ast_format_cap_alloc_nolock(); 00489 struct ast_format tmpfmt; 00490 int cause; 00491 00492 ao2_lock(conference_bridge); 00493 if (conference_bridge->record_chan || conference_bridge->record_thread != AST_PTHREADT_NULL) { 00494 ao2_unlock(conference_bridge); 00495 return -1; /* already recording */ 00496 } 00497 if (!cap) { 00498 ao2_unlock(conference_bridge); 00499 return -1; 00500 } 00501 if (!pbx_findapp("MixMonitor")) { 00502 ast_log(LOG_WARNING, "Can not record ConfBridge, MixMonitor app is not installed\n"); 00503 cap = ast_format_cap_destroy(cap); 00504 ao2_unlock(conference_bridge); 00505 return -1; 00506 } 00507 ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); 00508 if (!(conference_bridge->record_chan = ast_request("ConfBridgeRec", cap, NULL, conference_bridge->name, &cause))) { 00509 cap = ast_format_cap_destroy(cap); 00510 ao2_unlock(conference_bridge); 00511 return -1; 00512 } 00513 00514 cap = ast_format_cap_destroy(cap); 00515 ao2_ref(conference_bridge, +1); /* give the record thread a ref */ 00516 00517 if (ast_pthread_create_background(&conference_bridge->record_thread, NULL, record_thread, conference_bridge)) { 00518 ast_log(LOG_WARNING, "Failed to create recording channel for conference %s\n", conference_bridge->name); 00519 00520 ao2_unlock(conference_bridge); 00521 ao2_ref(conference_bridge, -1); /* error so remove ref */ 00522 return -1; 00523 } 00524 00525 ast_test_suite_event_notify("CONF_START_RECORD", "Message: started conference recording channel\r\nConference: %s", conference_bridge->b_profile.name); 00526 ao2_unlock(conference_bridge); 00527 return 0; 00528 }
| static int conf_stop_record | ( | struct conference_bridge * | conference_bridge | ) | [static] |
Definition at line 458 of file app_confbridge.c.
References ao2_lock, ao2_unlock, ast_bridge_remove(), ast_channel_ref, ast_channel_unref, ast_null_frame, AST_PTHREADT_NULL, ast_queue_frame(), ast_test_suite_event_notify, and thread.
Referenced by action_confbridgestoprecord(), handle_cli_confbridge_stop_record(), and leave_conference_bridge().
00459 { 00460 ao2_lock(conference_bridge); 00461 00462 if (conference_bridge->record_thread != AST_PTHREADT_NULL) { 00463 struct ast_channel *chan = ast_channel_ref(conference_bridge->record_chan); 00464 pthread_t thread = conference_bridge->record_thread; 00465 ao2_unlock(conference_bridge); 00466 00467 ast_bridge_remove(conference_bridge->bridge, chan); 00468 ast_queue_frame(chan, &ast_null_frame); 00469 00470 chan = ast_channel_unref(chan); 00471 pthread_join(thread, NULL); 00472 ast_test_suite_event_notify("CONF_STOP_RECORD", "Message: stopped conference recording channel\r\nConference: %s", conference_bridge->b_profile.name); 00473 00474 ao2_lock(conference_bridge); 00475 } 00476 00477 /* this is the reference given to the channel during the channel alloc */ 00478 if (conference_bridge->record_chan) { 00479 conference_bridge->record_chan = ast_channel_unref(conference_bridge->record_chan); 00480 } 00481 00482 ao2_unlock(conference_bridge); 00483 return 0; 00484 }
| static int confbridge_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
The ConfBridge application.
Definition at line 1308 of file app_confbridge.c.
References ast_channel::_state, 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_features_set_talk_detector(), ast_bridge_join(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_filedelete(), ast_free, ast_func_write(), ast_log(), ast_module_helper(), ast_moh_start(), ast_moh_stop(), ast_shutting_down(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdup, ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, conf_get_pin(), conf_get_sound(), conf_handle_talker_cb(), conf_handle_talker_destructor(), conf_rec_name(), DEFAULT_SILENCE_THRESHOLD, handle_video_on_exit(), handle_video_on_join(), join_conference_bridge(), leave_conference_bridge(), LOG_WARNING, parse(), play_sound_file(), send_join_event(), and send_leave_event().
Referenced by load_module().
01309 { 01310 int res = 0, volume_adjustments[2]; 01311 int quiet = 0; 01312 char *parse; 01313 const char *b_profile_name = DEFAULT_BRIDGE_PROFILE; 01314 const char *u_profile_name = DEFAULT_USER_PROFILE; 01315 struct conference_bridge *conference_bridge = NULL; 01316 struct conference_bridge_user conference_bridge_user = { 01317 .chan = chan, 01318 .tech_args.talking_threshold = DEFAULT_TALKING_THRESHOLD, 01319 .tech_args.silence_threshold = DEFAULT_SILENCE_THRESHOLD, 01320 .tech_args.drop_silence = 0, 01321 }; 01322 AST_DECLARE_APP_ARGS(args, 01323 AST_APP_ARG(conf_name); 01324 AST_APP_ARG(b_profile_name); 01325 AST_APP_ARG(u_profile_name); 01326 AST_APP_ARG(menu_name); 01327 ); 01328 ast_bridge_features_init(&conference_bridge_user.features); 01329 01330 if (chan->_state != AST_STATE_UP) { 01331 ast_answer(chan); 01332 } 01333 01334 if (ast_strlen_zero(data)) { 01335 ast_log(LOG_WARNING, "%s requires an argument (conference name[,options])\n", app); 01336 res = -1; /* invalid PIN */ 01337 goto confbridge_cleanup; 01338 } 01339 01340 /* We need to make a copy of the input string if we are going to modify it! */ 01341 parse = ast_strdupa(data); 01342 01343 AST_STANDARD_APP_ARGS(args, parse); 01344 01345 /* bridge profile name */ 01346 if (args.argc > 1 && !ast_strlen_zero(args.b_profile_name)) { 01347 b_profile_name = args.b_profile_name; 01348 } 01349 if (!conf_find_bridge_profile(chan, b_profile_name, &conference_bridge_user.b_profile)) { 01350 ast_log(LOG_WARNING, "Conference bridge profile %s does not exist\n", b_profile_name); 01351 res = -1; 01352 goto confbridge_cleanup; 01353 } 01354 01355 /* user profile name */ 01356 if (args.argc > 2 && !ast_strlen_zero(args.u_profile_name)) { 01357 u_profile_name = args.u_profile_name; 01358 } 01359 01360 if (!conf_find_user_profile(chan, u_profile_name, &conference_bridge_user.u_profile)) { 01361 ast_log(LOG_WARNING, "Conference user profile %s does not exist\n", u_profile_name); 01362 res = -1; 01363 goto confbridge_cleanup; 01364 } 01365 quiet = ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_QUIET); 01366 01367 /* ask for a PIN immediately after finding user profile. This has to be 01368 * prompted for requardless of quiet setting. */ 01369 if (!ast_strlen_zero(conference_bridge_user.u_profile.pin)) { 01370 if (conf_get_pin(chan, &conference_bridge_user)) { 01371 res = -1; /* invalid PIN */ 01372 goto confbridge_cleanup; 01373 } 01374 } 01375 01376 /* See if we need them to record a intro name */ 01377 if (!quiet && ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_ANNOUNCE_JOIN_LEAVE)) { 01378 conf_rec_name(&conference_bridge_user, args.conf_name); 01379 } 01380 01381 /* menu name */ 01382 if (args.argc > 3 && !ast_strlen_zero(args.menu_name)) { 01383 ast_copy_string(conference_bridge_user.menu_name, args.menu_name, sizeof(conference_bridge_user.menu_name)); 01384 if (conf_set_menu_to_user(conference_bridge_user.menu_name, &conference_bridge_user)) { 01385 ast_log(LOG_WARNING, "Conference menu %s does not exist and can not be applied to confbridge user.\n", 01386 args.menu_name); 01387 res = -1; /* invalid PIN */ 01388 goto confbridge_cleanup; 01389 } 01390 } 01391 01392 /* Set if DTMF should pass through for this user or not */ 01393 if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DTMF_PASS)) { 01394 conference_bridge_user.features.dtmf_passthrough = 1; 01395 } 01396 01397 /* Set dsp threshold values if present */ 01398 if (conference_bridge_user.u_profile.talking_threshold) { 01399 conference_bridge_user.tech_args.talking_threshold = conference_bridge_user.u_profile.talking_threshold; 01400 } 01401 if (conference_bridge_user.u_profile.silence_threshold) { 01402 conference_bridge_user.tech_args.silence_threshold = conference_bridge_user.u_profile.silence_threshold; 01403 } 01404 01405 /* Set a talker indicate call back if talking detection is requested */ 01406 if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_TALKER_DETECT)) { 01407 char *conf_name = ast_strdup(args.conf_name); /* this is freed during feature cleanup */ 01408 if (!(conf_name)) { 01409 res = -1; /* invalid PIN */ 01410 goto confbridge_cleanup; 01411 } 01412 ast_bridge_features_set_talk_detector(&conference_bridge_user.features, 01413 conf_handle_talker_cb, 01414 conf_handle_talker_destructor, 01415 conf_name); 01416 } 01417 01418 /* Look for a conference bridge matching the provided name */ 01419 if (!(conference_bridge = join_conference_bridge(args.conf_name, &conference_bridge_user))) { 01420 res = -1; /* invalid PIN */ 01421 goto confbridge_cleanup; 01422 } 01423 01424 /* Keep a copy of volume adjustments so we can restore them later if need be */ 01425 volume_adjustments[0] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_READ); 01426 volume_adjustments[1] = ast_audiohook_volume_get(chan, AST_AUDIOHOOK_DIRECTION_WRITE); 01427 01428 /* If the caller should be joined already muted, make it so */ 01429 if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_STARTMUTED)) { 01430 conference_bridge_user.features.mute = 1; 01431 } 01432 01433 if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DROP_SILENCE)) { 01434 conference_bridge_user.tech_args.drop_silence = 1; 01435 } 01436 01437 if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_JITTERBUFFER)) { 01438 char *func_jb; 01439 if ((func_jb = ast_module_helper("", "func_jitterbuffer", 0, 0, 0, 0))) { 01440 ast_free(func_jb); 01441 ast_func_write(chan, "JITTERBUFFER(adaptive)", "default"); 01442 } 01443 } 01444 01445 if (ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_DENOISE)) { 01446 char *mod_speex; 01447 /* Reduce background noise from each participant */ 01448 if ((mod_speex = ast_module_helper("", "codec_speex", 0, 0, 0, 0))) { 01449 ast_free(mod_speex); 01450 ast_func_write(chan, "DENOISE(rx)", "on"); 01451 } 01452 } 01453 01454 /* if this user has a intro, play it before entering */ 01455 if (!ast_strlen_zero(conference_bridge_user.name_rec_location)) { 01456 ast_autoservice_start(chan); 01457 play_sound_file(conference_bridge, conference_bridge_user.name_rec_location); 01458 play_sound_file(conference_bridge, 01459 conf_get_sound(CONF_SOUND_HAS_JOINED, conference_bridge_user.b_profile.sounds)); 01460 ast_autoservice_stop(chan); 01461 } 01462 01463 /* Play the Join sound to both the conference and the user entering. */ 01464 if (!quiet) { 01465 const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference_bridge_user.b_profile.sounds); 01466 if (conference_bridge_user.playing_moh) { 01467 ast_moh_stop(chan); 01468 } 01469 ast_stream_and_wait(chan, join_sound, ""); 01470 ast_autoservice_start(chan); 01471 play_sound_file(conference_bridge, join_sound); 01472 ast_autoservice_stop(chan); 01473 if (conference_bridge_user.playing_moh) { 01474 ast_moh_start(chan, conference_bridge_user.u_profile.moh_class, NULL); 01475 } 01476 } 01477 01478 /* See if we need to automatically set this user as a video source or not */ 01479 handle_video_on_join(conference_bridge, conference_bridge_user.chan, ast_test_flag(&conference_bridge_user.u_profile, USER_OPT_MARKEDUSER)); 01480 01481 /* Join our conference bridge for real */ 01482 send_join_event(conference_bridge_user.chan, conference_bridge->name); 01483 ast_bridge_join(conference_bridge->bridge, 01484 chan, 01485 NULL, 01486 &conference_bridge_user.features, 01487 &conference_bridge_user.tech_args); 01488 send_leave_event(conference_bridge_user.chan, conference_bridge->name); 01489 01490 /* if we're shutting down, don't attempt to do further processing */ 01491 if (ast_shutting_down()) { 01492 leave_conference_bridge(conference_bridge, &conference_bridge_user); 01493 conference_bridge = NULL; 01494 goto confbridge_cleanup; 01495 } 01496 01497 /* If this user was a video source, we need to clean up and possibly pick a new source. */ 01498 handle_video_on_exit(conference_bridge, conference_bridge_user.chan); 01499 01500 /* if this user has a intro, play it when leaving */ 01501 if (!quiet && !ast_strlen_zero(conference_bridge_user.name_rec_location)) { 01502 ast_autoservice_start(chan); 01503 play_sound_file(conference_bridge, conference_bridge_user.name_rec_location); 01504 play_sound_file(conference_bridge, 01505 conf_get_sound(CONF_SOUND_HAS_LEFT, conference_bridge_user.b_profile.sounds)); 01506 ast_autoservice_stop(chan); 01507 } 01508 01509 /* play the leave sound */ 01510 if (!quiet) { 01511 const char *leave_sound = conf_get_sound(CONF_SOUND_LEAVE, conference_bridge_user.b_profile.sounds); 01512 ast_autoservice_start(chan); 01513 play_sound_file(conference_bridge, leave_sound); 01514 ast_autoservice_stop(chan); 01515 } 01516 01517 /* Easy as pie, depart this channel from the conference bridge */ 01518 leave_conference_bridge(conference_bridge, &conference_bridge_user); 01519 conference_bridge = NULL; 01520 01521 /* If the user was kicked from the conference play back the audio prompt for it */ 01522 if (!quiet && conference_bridge_user.kicked) { 01523 res = ast_stream_and_wait(chan, 01524 conf_get_sound(CONF_SOUND_KICKED, conference_bridge_user.b_profile.sounds), 01525 ""); 01526 } 01527 01528 /* Restore volume adjustments to previous values in case they were changed */ 01529 if (volume_adjustments[0]) { 01530 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_READ, volume_adjustments[0]); 01531 } 01532 if (volume_adjustments[1]) { 01533 ast_audiohook_volume_set(chan, AST_AUDIOHOOK_DIRECTION_WRITE, volume_adjustments[1]); 01534 } 01535 01536 if (!ast_strlen_zero(conference_bridge_user.name_rec_location)) { 01537 ast_filedelete(conference_bridge_user.name_rec_location, NULL); 01538 } 01539 01540 confbridge_cleanup: 01541 ast_bridge_features_cleanup(&conference_bridge_user.features); 01542 conf_bridge_profile_destroy(&conference_bridge_user.b_profile); 01543 return res; 01544 }
| static int conference_bridge_cmp_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
Comparison function used for conference bridges container.
Definition at line 295 of file app_confbridge.c.
References CMP_MATCH, and CMP_STOP.
Referenced by load_module().
00296 { 00297 const struct conference_bridge *conference_bridge0 = obj, *conference_bridge1 = arg; 00298 return (!strcasecmp(conference_bridge0->name, conference_bridge1->name) ? CMP_MATCH | CMP_STOP : 0); 00299 }
| static int conference_bridge_hash_cb | ( | const void * | obj, | |
| const int | flags | |||
| ) | [static] |
Hashing function used for conference bridges container.
Definition at line 288 of file app_confbridge.c.
References ast_str_case_hash().
Referenced by load_module().
00289 { 00290 const struct conference_bridge *conference_bridge = obj; 00291 return ast_str_case_hash(conference_bridge->name); 00292 }
| static void destroy_conference_bridge | ( | void * | obj | ) | [static] |
Destroy a conference bridge.
| obj | The conference bridge object |
Definition at line 867 of file app_confbridge.c.
References ast_bridge_destroy(), ast_debug, ast_hangup(), and ast_mutex_destroy.
Referenced by join_conference_bridge().
00868 { 00869 struct conference_bridge *conference_bridge = obj; 00870 00871 ast_debug(1, "Destroying conference bridge '%s'\n", conference_bridge->name); 00872 00873 ast_mutex_destroy(&conference_bridge->playback_lock); 00874 00875 if (conference_bridge->playback_chan) { 00876 struct ast_channel *underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL); 00877 if (underlying_channel) { 00878 ast_hangup(underlying_channel); 00879 } 00880 ast_hangup(conference_bridge->playback_chan); 00881 conference_bridge->playback_chan = NULL; 00882 } 00883 00884 /* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */ 00885 if (conference_bridge->bridge) { 00886 ast_bridge_destroy(conference_bridge->bridge); 00887 conference_bridge->bridge = NULL; 00888 } 00889 conf_bridge_profile_destroy(&conference_bridge->b_profile); 00890 }
| static int execute_menu_entry | ( | struct conference_bridge * | conference_bridge, | |
| struct conference_bridge_user * | conference_bridge_user, | |||
| struct ast_bridge_channel * | bridge_channel, | |||
| struct conf_menu_entry * | menu_entry, | |||
| struct conf_menu * | menu | |||
| ) | [static] |
Definition at line 1753 of file app_confbridge.c.
References action_dialplan_exec(), action_kick_last(), action_playback(), action_playback_and_continue(), action_toggle_mute(), action_toggle_mute_participants(), 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_LIST_TRAVERSE, ast_stream_and_wait(), ast_test_flag, ast_bridge_channel::chan, conf_get_sound(), and handle_video_on_exit().
Referenced by action_playback_and_continue(), and conf_handle_dtmf().
01758 { 01759 struct conf_menu_action *menu_action; 01760 int isadmin = ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN); 01761 int stop_prompts = 0; 01762 int res = 0; 01763 01764 AST_LIST_TRAVERSE(&menu_entry->actions, menu_action, action) { 01765 switch (menu_action->id) { 01766 case MENU_ACTION_TOGGLE_MUTE: 01767 res |= action_toggle_mute(conference_bridge, 01768 conference_bridge_user, 01769 bridge_channel->chan); 01770 break; 01771 case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS: 01772 if (!isadmin) { 01773 break; 01774 } 01775 action_toggle_mute_participants(conference_bridge, conference_bridge_user); 01776 break; 01777 case MENU_ACTION_PARTICIPANT_COUNT: 01778 announce_user_count(conference_bridge, conference_bridge_user); 01779 break; 01780 case MENU_ACTION_PLAYBACK: 01781 if (!stop_prompts) { 01782 res |= action_playback(bridge_channel, menu_action->data.playback_file); 01783 } 01784 break; 01785 case MENU_ACTION_RESET_LISTENING: 01786 ast_audiohook_volume_set(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_WRITE, 0); 01787 break; 01788 case MENU_ACTION_RESET_TALKING: 01789 ast_audiohook_volume_set(conference_bridge_user->chan, AST_AUDIOHOOK_DIRECTION_READ, 0); 01790 break; 01791 case MENU_ACTION_INCREASE_LISTENING: 01792 ast_audiohook_volume_adjust(conference_bridge_user->chan, 01793 AST_AUDIOHOOK_DIRECTION_WRITE, 1); 01794 break; 01795 case MENU_ACTION_DECREASE_LISTENING: 01796 ast_audiohook_volume_adjust(conference_bridge_user->chan, 01797 AST_AUDIOHOOK_DIRECTION_WRITE, -1); 01798 break; 01799 case MENU_ACTION_INCREASE_TALKING: 01800 ast_audiohook_volume_adjust(conference_bridge_user->chan, 01801 AST_AUDIOHOOK_DIRECTION_READ, 1); 01802 break; 01803 case MENU_ACTION_DECREASE_TALKING: 01804 ast_audiohook_volume_adjust(conference_bridge_user->chan, 01805 AST_AUDIOHOOK_DIRECTION_READ, -1); 01806 break; 01807 case MENU_ACTION_PLAYBACK_AND_CONTINUE: 01808 if (!(stop_prompts)) { 01809 res |= action_playback_and_continue(conference_bridge, 01810 conference_bridge_user, 01811 bridge_channel, 01812 menu, 01813 menu_action->data.playback_file, 01814 menu_entry->dtmf, 01815 &stop_prompts); 01816 } 01817 break; 01818 case MENU_ACTION_DIALPLAN_EXEC: 01819 res |= action_dialplan_exec(bridge_channel, menu_action); 01820 break; 01821 case MENU_ACTION_ADMIN_TOGGLE_LOCK: 01822 if (!isadmin) { 01823 break; 01824 } 01825 conference_bridge->locked = (!conference_bridge->locked ? 1 : 0); 01826 res |= ast_stream_and_wait(bridge_channel->chan, 01827 (conference_bridge->locked ? 01828 conf_get_sound(CONF_SOUND_LOCKED_NOW, conference_bridge_user->b_profile.sounds) : 01829 conf_get_sound(CONF_SOUND_UNLOCKED_NOW, conference_bridge_user->b_profile.sounds)), 01830 ""); 01831 01832 break; 01833 case MENU_ACTION_ADMIN_KICK_LAST: 01834 res |= action_kick_last(conference_bridge, bridge_channel, conference_bridge_user); 01835 break; 01836 case MENU_ACTION_LEAVE: 01837 ao2_lock(conference_bridge); 01838 ast_bridge_remove(conference_bridge->bridge, bridge_channel->chan); 01839 ao2_unlock(conference_bridge); 01840 break; 01841 case MENU_ACTION_NOOP: 01842 break; 01843 case MENU_ACTION_SET_SINGLE_VIDEO_SRC: 01844 ao2_lock(conference_bridge); 01845 ast_bridge_set_single_src_video_mode(conference_bridge->bridge, bridge_channel->chan); 01846 ao2_unlock(conference_bridge); 01847 break; 01848 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC: 01849 handle_video_on_exit(conference_bridge, bridge_channel->chan); 01850 break; 01851 } 01852 } 01853 return res; 01854 }
| static int func_confbridge_info | ( | struct ast_channel * | chan, | |
| const char * | cmd, | |||
| char * | data, | |||
| char * | buf, | |||
| size_t | len | |||
| ) | [static] |
Definition at line 2658 of file app_confbridge.c.
References ao2_container_count(), ao2_find, ao2_lock, ao2_ref, ao2_unlock, args, AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_TRAVERSE, ast_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, LOG_ERROR, OBJ_POINTER, parse(), and type.
02659 { 02660 char *parse = NULL; 02661 struct conference_bridge *bridge = NULL; 02662 struct conference_bridge_user *participant = NULL; 02663 struct conference_bridge tmp; 02664 int count = 0; 02665 AST_DECLARE_APP_ARGS(args, 02666 AST_APP_ARG(type); 02667 AST_APP_ARG(confno); 02668 ); 02669 02670 /* parse all the required arguments and make sure they exist. */ 02671 if (ast_strlen_zero(data)) { 02672 return -1; 02673 } 02674 parse = ast_strdupa(data); 02675 AST_STANDARD_APP_ARGS(args, parse); 02676 if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) { 02677 return -1; 02678 } 02679 if (!ao2_container_count(conference_bridges)) { 02680 snprintf(buf, len, "0"); 02681 return 0; 02682 } 02683 ast_copy_string(tmp.name, args.confno, sizeof(tmp.name)); 02684 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 02685 if (!bridge) { 02686 snprintf(buf, len, "0"); 02687 return 0; 02688 } 02689 02690 /* get the correct count for the type requested */ 02691 ao2_lock(bridge); 02692 if (!strncasecmp(args.type, "parties", 7)) { 02693 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { 02694 count++; 02695 } 02696 } else if (!strncasecmp(args.type, "admins", 6)) { 02697 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { 02698 if (ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) { 02699 count++; 02700 } 02701 } 02702 } else if (!strncasecmp(args.type, "marked", 6)) { 02703 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { 02704 if (ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER)) { 02705 count++; 02706 } 02707 } 02708 } else if (!strncasecmp(args.type, "locked", 6)) { 02709 count = bridge->locked; 02710 } else { 02711 ast_log(LOG_ERROR, "Invalid keyword '%s' passed to CONFBRIDGE_INFO. Should be one of: " 02712 "parties, admins, marked, or locked.\n", args.type); 02713 } 02714 snprintf(buf, len, "%d", count); 02715 ao2_unlock(bridge); 02716 ao2_ref(bridge, -1); 02717 return 0; 02718 }
| static int generic_lock_unlock_helper | ( | int | lock, | |
| const char * | conference | |||
| ) | [static] |
Definition at line 2022 of file app_confbridge.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_test_suite_event_notify, and OBJ_POINTER.
Referenced by action_lock_unlock_helper(), handle_cli_confbridge_lock(), and handle_cli_confbridge_unlock().
02023 { 02024 struct conference_bridge *bridge = NULL; 02025 struct conference_bridge tmp; 02026 int res = 0; 02027 02028 ast_copy_string(tmp.name, conference, sizeof(tmp.name)); 02029 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 02030 if (!bridge) { 02031 return -1; 02032 } 02033 ao2_lock(bridge); 02034 bridge->locked = lock; 02035 ast_test_suite_event_notify("CONF_LOCK", "Message: conference %s\r\nConference: %s", bridge->locked ? "locked" : "unlocked", bridge->b_profile.name); 02036 ao2_unlock(bridge); 02037 ao2_ref(bridge, -1); 02038 02039 return res; 02040 }
| static int generic_mute_unmute_helper | ( | int | mute, | |
| const char * | conference, | |||
| const char * | user | |||
| ) | [static] |
Definition at line 2049 of file app_confbridge.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_channel_name(), ast_copy_string(), AST_LIST_TRAVERSE, ast_test_suite_event_notify, and OBJ_POINTER.
Referenced by action_mute_unmute_helper(), and cli_mute_unmute_helper().
02050 { 02051 struct conference_bridge *bridge = NULL; 02052 struct conference_bridge tmp; 02053 struct conference_bridge_user *participant = NULL; 02054 int res = 0; 02055 ast_copy_string(tmp.name, conference, sizeof(tmp.name)); 02056 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 02057 if (!bridge) { 02058 return -1; 02059 } 02060 ao2_lock(bridge); 02061 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { 02062 if (!strncmp(user, ast_channel_name(participant->chan), strlen(user))) { 02063 break; 02064 } 02065 } 02066 if (participant) { 02067 participant->features.mute = mute; 02068 ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(participant->chan), participant->features.mute ? "muted" : "unmuted", bridge->b_profile.name, ast_channel_name(participant->chan)); 02069 } else { 02070 res = -2;; 02071 } 02072 ao2_unlock(bridge); 02073 ao2_ref(bridge, -1); 02074 02075 return res; 02076 }
| static char* handle_cli_confbridge_kick | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1906 of file app_confbridge.c.
References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_cli_args::argc, ast_cli_args::argv, ast_bridge_remove(), ast_channel_name(), ast_cli(), ast_copy_string(), AST_LIST_TRAVERSE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, OBJ_POINTER, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
01907 { 01908 struct conference_bridge *bridge = NULL; 01909 struct conference_bridge tmp; 01910 struct conference_bridge_user *participant = NULL; 01911 01912 switch (cmd) { 01913 case CLI_INIT: 01914 e->command = "confbridge kick"; 01915 e->usage = 01916 "Usage: confbridge kick <conference> <channel>\n" 01917 " Kicks a channel out of the conference bridge.\n"; 01918 return NULL; 01919 case CLI_GENERATE: 01920 if (a->pos == 2) { 01921 return complete_confbridge_name(a->line, a->word, a->pos, a->n); 01922 } 01923 /* 01924 if (a->pos == 3) { 01925 return complete_confbridge_channel(a->line, a->word, a->pos, a->n); 01926 } 01927 */ 01928 return NULL; 01929 } 01930 01931 if (a->argc != 4) { 01932 return CLI_SHOWUSAGE; 01933 } 01934 01935 ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name)); 01936 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 01937 if (!bridge) { 01938 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]); 01939 return CLI_SUCCESS; 01940 } 01941 ao2_lock(bridge); 01942 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { 01943 if (!strncmp(a->argv[3], ast_channel_name(participant->chan), strlen(ast_channel_name(participant->chan)))) { 01944 break; 01945 } 01946 } 01947 if (participant) { 01948 ast_cli(a->fd, "Kicking %s from confbridge %s\n", ast_channel_name(participant->chan), bridge->name); 01949 participant->kicked = 1; 01950 ast_bridge_remove(bridge->bridge, participant->chan); 01951 } 01952 ao2_unlock(bridge); 01953 ao2_ref(bridge, -1); 01954 return CLI_SUCCESS; 01955 }
| static char* handle_cli_confbridge_list | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 1957 of file app_confbridge.c.
References 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_channel_name(), ast_cli(), ast_copy_string(), AST_LIST_TRAVERSE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, OBJ_POINTER, ast_cli_args::pos, S_COR, ast_cli_entry::usage, and ast_cli_args::word.
01958 { 01959 struct ao2_iterator i; 01960 struct conference_bridge *bridge = NULL; 01961 struct conference_bridge tmp; 01962 struct conference_bridge_user *participant = NULL; 01963 01964 switch (cmd) { 01965 case CLI_INIT: 01966 e->command = "confbridge list"; 01967 e->usage = 01968 "Usage: confbridge list [<name>]\n" 01969 " Lists all currently active conference bridges.\n"; 01970 return NULL; 01971 case CLI_GENERATE: 01972 if (a->pos == 2) { 01973 return complete_confbridge_name(a->line, a->word, a->pos, a->n); 01974 } 01975 return NULL; 01976 } 01977 01978 if (a->argc == 2) { 01979 ast_cli(a->fd, "Conference Bridge Name Users Marked Locked?\n"); 01980 ast_cli(a->fd, "================================ ====== ====== ========\n"); 01981 i = ao2_iterator_init(conference_bridges, 0); 01982 while ((bridge = ao2_iterator_next(&i))) { 01983 ast_cli(a->fd, "%-32s %6i %6i %s\n", bridge->name, bridge->users, bridge->markedusers, (bridge->locked ? "locked" : "unlocked")); 01984 ao2_ref(bridge, -1); 01985 } 01986 ao2_iterator_destroy(&i); 01987 return CLI_SUCCESS; 01988 } 01989 01990 if (a->argc == 3) { 01991 ast_copy_string(tmp.name, a->argv[2], sizeof(tmp.name)); 01992 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 01993 if (!bridge) { 01994 ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]); 01995 return CLI_SUCCESS; 01996 } 01997 ast_cli(a->fd, "Channel User Profile Bridge Profile Menu CallerID\n"); 01998 ast_cli(a->fd, "============================= ================ ================ ================ ================\n"); 01999 ao2_lock(bridge); 02000 AST_LIST_TRAVERSE(&bridge->users_list, participant, list) { 02001 ast_cli(a->fd, "%-29s ", ast_channel_name(participant->chan)); 02002 ast_cli(a->fd, "%-17s", participant->u_profile.name); 02003 ast_cli(a->fd, "%-17s", participant->b_profile.name); 02004 ast_cli(a->fd, "%-17s", participant->menu_name); 02005 ast_cli(a->fd, "%-17s", S_COR(participant->chan->caller.id.number.valid, participant->chan->caller.id.number.str, "<unknown>")); 02006 ast_cli(a->fd, "\n"); 02007 } 02008 ao2_unlock(bridge); 02009 ao2_ref(bridge, -1); 02010 return CLI_SUCCESS; 02011 } 02012 02013 return CLI_SHOWUSAGE; 02014 }
| static char* handle_cli_confbridge_lock | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2139 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, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
02140 { 02141 switch (cmd) { 02142 case CLI_INIT: 02143 e->command = "confbridge lock"; 02144 e->usage = 02145 "Usage: confbridge lock <conference>\n"; 02146 return NULL; 02147 case CLI_GENERATE: 02148 if (a->pos == 2) { 02149 return complete_confbridge_name(a->line, a->word, a->pos, a->n); 02150 } 02151 return NULL; 02152 } 02153 if (a->argc != 3) { 02154 return CLI_SHOWUSAGE; 02155 } 02156 if (generic_lock_unlock_helper(1, a->argv[2])) { 02157 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]); 02158 } else { 02159 ast_cli(a->fd, "Conference %s is locked.\n", a->argv[2]); 02160 } 02161 return CLI_SUCCESS; 02162 }
| static char* handle_cli_confbridge_mute | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2093 of file app_confbridge.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, cli_mute_unmute_helper(), CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
02094 { 02095 switch (cmd) { 02096 case CLI_INIT: 02097 e->command = "confbridge mute"; 02098 e->usage = 02099 "Usage: confbridge mute <conference> <channel>\n"; 02100 return NULL; 02101 case CLI_GENERATE: 02102 if (a->pos == 2) { 02103 return complete_confbridge_name(a->line, a->word, a->pos, a->n); 02104 } 02105 return NULL; 02106 } 02107 if (a->argc != 4) { 02108 return CLI_SHOWUSAGE; 02109 } 02110 02111 cli_mute_unmute_helper(1, a); 02112 02113 return CLI_SUCCESS; 02114 }
| static char* handle_cli_confbridge_start_record | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2189 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(), 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, OBJ_POINTER, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
02190 { 02191 const char *rec_file = NULL; 02192 struct conference_bridge *bridge = NULL; 02193 struct conference_bridge tmp; 02194 02195 switch (cmd) { 02196 case CLI_INIT: 02197 e->command = "confbridge record start"; 02198 e->usage = 02199 "Usage: confbridge record start <conference> <file>\n" 02200 " <file> is optional, Otherwise the bridge profile\n" 02201 " record file will be used. If the bridge profile\n" 02202 " has no record file specified, a file will automatically\n" 02203 " be generated in the monitor directory\n"; 02204 return NULL; 02205 case CLI_GENERATE: 02206 if (a->pos == 3) { 02207 return complete_confbridge_name(a->line, a->word, a->pos, a->n); 02208 } 02209 return NULL; 02210 } 02211 if (a->argc < 4) { 02212 return CLI_SHOWUSAGE; 02213 } 02214 if (a->argc == 5) { 02215 rec_file = a->argv[4]; 02216 } 02217 02218 ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name)); 02219 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 02220 if (!bridge) { 02221 ast_cli(a->fd, "Conference not found.\n"); 02222 return CLI_FAILURE; 02223 } 02224 if (conf_is_recording(bridge)) { 02225 ast_cli(a->fd, "Conference is already being recorded.\n"); 02226 ao2_ref(bridge, -1); 02227 return CLI_SUCCESS; 02228 } 02229 if (!ast_strlen_zero(rec_file)) { 02230 ao2_lock(bridge); 02231 ast_copy_string(bridge->b_profile.rec_file, rec_file, sizeof(bridge->b_profile.rec_file)); 02232 ao2_unlock(bridge); 02233 } 02234 if (conf_start_record(bridge)) { 02235 ast_cli(a->fd, "Could not start recording due to internal error.\n"); 02236 ao2_ref(bridge, -1); 02237 return CLI_FAILURE; 02238 } 02239 ast_cli(a->fd, "Recording started\n"); 02240 ao2_ref(bridge, -1); 02241 return CLI_SUCCESS; 02242 }
| static char* handle_cli_confbridge_stop_record | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2244 of file app_confbridge.c.
References ao2_find, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_copy_string(), 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, OBJ_POINTER, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
02245 { 02246 struct conference_bridge *bridge = NULL; 02247 struct conference_bridge tmp; 02248 02249 switch (cmd) { 02250 case CLI_INIT: 02251 e->command = "confbridge record stop"; 02252 e->usage = 02253 "Usage: confbridge record stop <conference>\n"; 02254 return NULL; 02255 case CLI_GENERATE: 02256 if (a->pos == 3) { 02257 return complete_confbridge_name(a->line, a->word, a->pos, a->n); 02258 } 02259 return NULL; 02260 } 02261 if (a->argc != 4) { 02262 return CLI_SHOWUSAGE; 02263 } 02264 02265 ast_copy_string(tmp.name, a->argv[3], sizeof(tmp.name)); 02266 bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 02267 if (!bridge) { 02268 ast_cli(a->fd, "Conference not found.\n"); 02269 return CLI_SUCCESS; 02270 } 02271 conf_stop_record(bridge); 02272 ast_cli(a->fd, "Recording stopped.\n"); 02273 ao2_ref(bridge, -1); 02274 return CLI_SUCCESS; 02275 }
| static char* handle_cli_confbridge_unlock | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2164 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, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
02165 { 02166 switch (cmd) { 02167 case CLI_INIT: 02168 e->command = "confbridge unlock"; 02169 e->usage = 02170 "Usage: confbridge unlock <conference>\n"; 02171 return NULL; 02172 case CLI_GENERATE: 02173 if (a->pos == 2) { 02174 return complete_confbridge_name(a->line, a->word, a->pos, a->n); 02175 } 02176 return NULL; 02177 } 02178 if (a->argc != 3) { 02179 return CLI_SHOWUSAGE; 02180 } 02181 if (generic_lock_unlock_helper(0, a->argv[2])) { 02182 ast_cli(a->fd, "Conference %s is not found\n", a->argv[2]); 02183 } else { 02184 ast_cli(a->fd, "Conference %s is unlocked.\n", a->argv[2]); 02185 } 02186 return CLI_SUCCESS; 02187 }
| static char* handle_cli_confbridge_unmute | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 2116 of file app_confbridge.c.
References ast_cli_args::argc, CLI_GENERATE, CLI_INIT, cli_mute_unmute_helper(), CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_confbridge_name(), ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.
02117 { 02118 switch (cmd) { 02119 case CLI_INIT: 02120 e->command = "confbridge unmute"; 02121 e->usage = 02122 "Usage: confbridge unmute <conference> <channel>\n"; 02123 return NULL; 02124 case CLI_GENERATE: 02125 if (a->pos == 2) { 02126 return complete_confbridge_name(a->line, a->word, a->pos, a->n); 02127 } 02128 return NULL; 02129 } 02130 if (a->argc != 4) { 02131 return CLI_SHOWUSAGE; 02132 } 02133 02134 cli_mute_unmute_helper(0, a); 02135 02136 return CLI_SUCCESS; 02137 }
| static void handle_video_on_exit | ( | struct conference_bridge * | conference_bridge, | |
| struct ast_channel * | chan | |||
| ) | [static] |
Definition at line 677 of file app_confbridge.c.
References 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, and ast_test_flag.
Referenced by confbridge_exec(), and execute_menu_entry().
00678 { 00679 struct conference_bridge_user *tmp_user = NULL; 00680 00681 /* if this isn't a video source, nothing to update */ 00682 if (!ast_bridge_is_video_src(conference_bridge->bridge, chan)) { 00683 return; 00684 } 00685 00686 ast_bridge_remove_video_src(conference_bridge->bridge, chan); 00687 00688 /* If in follow talker mode, make sure to restore this mode on the 00689 * bridge when a source is removed. It is possible this channel was 00690 * only set temporarily as a video source by an AMI or DTMF action. */ 00691 if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) { 00692 ast_bridge_set_talker_src_video_mode(conference_bridge->bridge); 00693 } 00694 00695 /* if the video_mode isn't set to automatically pick the video source, do nothing on exit. */ 00696 if (!ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED) && 00697 !ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) { 00698 return; 00699 } 00700 00701 /* Make the next available marked user the video src. */ 00702 ao2_lock(conference_bridge); 00703 AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) { 00704 if (tmp_user->chan == chan) { 00705 continue; 00706 } 00707 if (ast_test_flag(&tmp_user->u_profile, USER_OPT_MARKEDUSER)) { 00708 ast_bridge_set_single_src_video_mode(conference_bridge->bridge, tmp_user->chan); 00709 break; 00710 } 00711 } 00712 ao2_unlock(conference_bridge); 00713 }
| static void handle_video_on_join | ( | struct conference_bridge * | conference_bridge, | |
| struct ast_channel * | chan, | |||
| int | marked | |||
| ) | [static] |
Definition at line 646 of file app_confbridge.c.
References ao2_lock, ao2_unlock, ast_bridge_is_video_src(), ast_bridge_set_single_src_video_mode(), AST_LIST_TRAVERSE, and ast_test_flag.
Referenced by confbridge_exec().
00647 { 00648 /* Right now, only marked users are automatically set as the single src of video.*/ 00649 if (!marked) { 00650 return; 00651 } 00652 00653 if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED)) { 00654 int set = 1; 00655 struct conference_bridge_user *tmp_user = NULL; 00656 ao2_lock(conference_bridge); 00657 /* see if anyone is already the video src */ 00658 AST_LIST_TRAVERSE(&conference_bridge->users_list, tmp_user, list) { 00659 if (tmp_user->chan == chan) { 00660 continue; 00661 } 00662 if (ast_bridge_is_video_src(conference_bridge->bridge, tmp_user->chan)) { 00663 set = 0; 00664 break; 00665 } 00666 } 00667 ao2_unlock(conference_bridge); 00668 if (set) { 00669 ast_bridge_set_single_src_video_mode(conference_bridge->bridge, chan); 00670 } 00671 } else if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_LAST_MARKED)) { 00672 /* we joined and are video capable, we override anyone else that may have already been the video feed */ 00673 ast_bridge_set_single_src_video_mode(conference_bridge->bridge, chan); 00674 } 00675 }
| static struct conference_bridge* join_conference_bridge | ( | const char * | name, | |
| struct conference_bridge_user * | conference_bridge_user | |||
| ) | [static, read] |
Join a conference bridge.
| name | The conference name | |
| conference_bridge_user | Conference bridge user structure |
Definition at line 902 of file app_confbridge.c.
References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, AST_BRIDGE_CAPABILITY_MULTIMIX, ast_bridge_new(), ast_bridge_set_internal_sample_rate(), ast_bridge_set_mixing_interval(), ast_bridge_set_talker_src_video_mode(), ast_copy_string(), ast_debug, AST_DEVICE_INUSE, ast_devstate_changed(), AST_LIST_INSERT_TAIL, ast_log(), ast_mutex_init, AST_PTHREADT_NULL, ast_stream_and_wait(), ast_test_flag, conf_get_sound(), conf_is_recording(), conf_start_record(), destroy_conference_bridge(), leave_conference_bridge(), LOG_ERROR, OBJ_POINTER, post_join_marked(), post_join_unmarked(), and send_conf_start_event().
Referenced by confbridge_exec().
00903 { 00904 struct conference_bridge *conference_bridge = NULL; 00905 struct conference_bridge tmp; 00906 int start_record = 0; 00907 int max_members_reached = 0; 00908 00909 ast_copy_string(tmp.name, name, sizeof(tmp.name)); 00910 00911 /* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */ 00912 ao2_lock(conference_bridges); 00913 00914 ast_debug(1, "Trying to find conference bridge '%s'\n", name); 00915 00916 /* Attempt to find an existing conference bridge */ 00917 conference_bridge = ao2_find(conference_bridges, &tmp, OBJ_POINTER); 00918 00919 if (conference_bridge && conference_bridge->b_profile.max_members) { 00920 max_members_reached = conference_bridge->b_profile.max_members > conference_bridge->users ? 0 : 1; 00921 } 00922 00923 /* When finding a conference bridge that already exists make sure that it is not locked, and if so that we are not an admin */ 00924 if (conference_bridge && (max_members_reached || conference_bridge->locked) && !ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN)) { 00925 ao2_unlock(conference_bridges); 00926 ao2_ref(conference_bridge, -1); 00927 ast_debug(1, "Conference bridge '%s' is locked and caller is not an admin\n", name); 00928 ast_stream_and_wait(conference_bridge_user->chan, 00929 conf_get_sound(CONF_SOUND_LOCKED, conference_bridge_user->b_profile.sounds), 00930 ""); 00931 return NULL; 00932 } 00933 00934 /* If no conference bridge was found see if we can create one */ 00935 if (!conference_bridge) { 00936 /* Try to allocate memory for a new conference bridge, if we fail... this won't end well. */ 00937 if (!(conference_bridge = ao2_alloc(sizeof(*conference_bridge), destroy_conference_bridge))) { 00938 ao2_unlock(conference_bridges); 00939 ast_log(LOG_ERROR, "Conference bridge '%s' does not exist.\n", name); 00940 return NULL; 00941 } 00942 00943 /* Setup conference bridge parameters */ 00944 conference_bridge->record_thread = AST_PTHREADT_NULL; 00945 ast_copy_string(conference_bridge->name, name, sizeof(conference_bridge->name)); 00946 conf_bridge_profile_copy(&conference_bridge->b_profile, &conference_bridge_user->b_profile); 00947 00948 /* Create an actual bridge that will do the audio mixing */ 00949 if (!(conference_bridge->bridge = ast_bridge_new(AST_BRIDGE_CAPABILITY_MULTIMIX, 0))) { 00950 ao2_ref(conference_bridge, -1); 00951 conference_bridge = NULL; 00952 ao2_unlock(conference_bridges); 00953 ast_log(LOG_ERROR, "Conference bridge '%s' could not be created.\n", name); 00954 return NULL; 00955 } 00956 00957 /* Set the internal sample rate on the bridge from the bridge profile */ 00958 ast_bridge_set_internal_sample_rate(conference_bridge->bridge, conference_bridge->b_profile.internal_sample_rate); 00959 /* Set the internal mixing interval on the bridge from the bridge profile */ 00960 ast_bridge_set_mixing_interval(conference_bridge->bridge, conference_bridge->b_profile.mix_interval); 00961 00962 if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER)) { 00963 ast_bridge_set_talker_src_video_mode(conference_bridge->bridge); 00964 } 00965 00966 /* Setup lock for playback channel */ 00967 ast_mutex_init(&conference_bridge->playback_lock); 00968 00969 /* Link it into the conference bridges container */ 00970 ao2_link(conference_bridges, conference_bridge); 00971 00972 00973 send_conf_start_event(conference_bridge->name); 00974 ast_debug(1, "Created conference bridge '%s' and linked to container '%p'\n", name, conference_bridges); 00975 } 00976 00977 ao2_unlock(conference_bridges); 00978 00979 /* Setup conference bridge user parameters */ 00980 conference_bridge_user->conference_bridge = conference_bridge; 00981 00982 ao2_lock(conference_bridge); 00983 00984 /* All good to go, add them in */ 00985 AST_LIST_INSERT_TAIL(&conference_bridge->users_list, conference_bridge_user, list); 00986 00987 /* Increment the users count on the bridge, but record it as it is going to need to be known right after this */ 00988 conference_bridge->users++; 00989 00990 /* If the caller is a marked user bump up the count */ 00991 if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) { 00992 conference_bridge->markedusers++; 00993 } 00994 00995 /* Set the device state for this conference */ 00996 if (conference_bridge->users == 1) { 00997 ast_devstate_changed(AST_DEVICE_INUSE, "confbridge:%s", conference_bridge->name); 00998 } 00999 01000 /* If the caller is a marked user or is waiting for a marked user to enter pass 'em off, otherwise pass them off to do regular joining stuff */ 01001 if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER | USER_OPT_WAITMARKED)) { 01002 if (post_join_marked(conference_bridge, conference_bridge_user)) { 01003 ao2_unlock(conference_bridge); 01004 leave_conference_bridge(conference_bridge, conference_bridge_user); 01005 return NULL; 01006 } 01007 } else { 01008 if (post_join_unmarked(conference_bridge, conference_bridge_user)) { 01009 ao2_unlock(conference_bridge); 01010 leave_conference_bridge(conference_bridge, conference_bridge_user); 01011 return NULL; 01012 } 01013 } 01014 01015 /* check to see if recording needs to be started or not */ 01016 if (ast_test_flag(&conference_bridge->b_profile, BRIDGE_OPT_RECORD_CONFERENCE) && !conf_is_recording(conference_bridge)) { 01017 start_record = 1; 01018 } 01019 01020 ao2_unlock(conference_bridge); 01021 01022 if (start_record) { 01023 conf_start_record(conference_bridge); 01024 } 01025 01026 return conference_bridge; 01027 }
| static void leave_conference_bridge | ( | struct conference_bridge * | conference_bridge, | |
| struct conference_bridge_user * | conference_bridge_user | |||
| ) | [static] |
Leave a conference bridge.
| conference_bridge | The conference bridge to leave | |
| conference_bridge_user | The conference bridge user structure |
Definition at line 1036 of file app_confbridge.c.
References ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, ast_autoservice_start(), ast_autoservice_stop(), ast_bridge_remove(), ast_bridge_suspend(), ast_bridge_unsuspend(), AST_DEVICE_NOT_INUSE, ast_devstate_changed(), AST_LIST_FIRST, AST_LIST_REMOVE, AST_LIST_TRAVERSE, ast_moh_start(), ast_test_flag, conf_get_sound(), conf_stop_record(), play_sound_file(), and send_conf_end_event().
Referenced by confbridge_exec(), and join_conference_bridge().
01037 { 01038 ao2_lock(conference_bridge); 01039 01040 /* If this caller is a marked user bump down the count */ 01041 if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) { 01042 conference_bridge->markedusers--; 01043 } 01044 01045 /* Decrement the users count while keeping the previous participant count */ 01046 conference_bridge->users--; 01047 01048 /* Drop conference bridge user from the list, they be going bye bye */ 01049 AST_LIST_REMOVE(&conference_bridge->users_list, conference_bridge_user, list); 01050 01051 /* If there are still users in the conference bridge we may need to do things (such as start MOH on them) */ 01052 if (conference_bridge->users) { 01053 if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER) && !conference_bridge->markedusers) { 01054 struct conference_bridge_user *other_participant = NULL; 01055 01056 /* Start out with muting everyone */ 01057 AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) { 01058 other_participant->features.mute = 1; 01059 } 01060 01061 /* Play back the audio prompt saying the leader has left the conference */ 01062 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) { 01063 ao2_unlock(conference_bridge); 01064 ast_autoservice_start(conference_bridge_user->chan); 01065 play_sound_file(conference_bridge, 01066 conf_get_sound(CONF_SOUND_LEADER_HAS_LEFT, conference_bridge_user->b_profile.sounds)); 01067 ast_autoservice_stop(conference_bridge_user->chan); 01068 ao2_lock(conference_bridge); 01069 } 01070 01071 /* Now on to starting MOH or kick if needed */ 01072 AST_LIST_TRAVERSE(&conference_bridge->users_list, other_participant, list) { 01073 if (ast_test_flag(&other_participant->u_profile, USER_OPT_ENDMARKED)) { 01074 other_participant->kicked = 1; 01075 ast_bridge_remove(conference_bridge->bridge, other_participant->chan); 01076 } else if (ast_test_flag(&other_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, other_participant->chan)) { 01077 ast_moh_start(other_participant->chan, other_participant->u_profile.moh_class, NULL); 01078 other_participant->playing_moh = 1; 01079 ast_bridge_unsuspend(conference_bridge->bridge, other_participant->chan); 01080 } 01081 } 01082 } else if (conference_bridge->users == 1) { 01083 /* Of course if there is one other person in here we may need to start up MOH on them */ 01084 struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list); 01085 01086 if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) { 01087 ast_moh_start(first_participant->chan, first_participant->u_profile.moh_class, NULL); 01088 first_participant->playing_moh = 1; 01089 ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan); 01090 } 01091 } 01092 } else { 01093 /* Set device state to "not in use" */ 01094 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "confbridge:%s", conference_bridge->name); 01095 01096 ao2_unlink(conference_bridges, conference_bridge); 01097 send_conf_end_event(conference_bridge->name); 01098 } 01099 01100 /* Done mucking with the conference bridge, huzzah */ 01101 ao2_unlock(conference_bridge); 01102 01103 if (!conference_bridge->users) { 01104 conf_stop_record(conference_bridge); 01105 } 01106 01107 ao2_ref(conference_bridge, -1); 01108 }
| static int load_module | ( | void | ) | [static] |
Called when module is being loaded.
Definition at line 2752 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, ao2_ref, ast_channel_register(), ast_cli_register_multiple(), ast_custom_function_register, ast_format_cap_add_all(), ast_format_cap_alloc(), ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_FAILURE, ast_register_application_xml, ast_channel_tech::capabilities, confbridge_exec(), CONFERENCE_BRIDGE_BUCKETS, conference_bridge_cmp_cb(), conference_bridge_hash_cb(), EVENT_FLAG_CALL, EVENT_FLAG_REPORTING, and LOG_ERROR.
02753 { 02754 int res = 0; 02755 if ((ast_custom_function_register(&confbridge_function))) { 02756 return AST_MODULE_LOAD_FAILURE; 02757 } 02758 if ((ast_custom_function_register(&confbridge_info_function))) { 02759 return AST_MODULE_LOAD_FAILURE; 02760 } 02761 if (!(record_tech.capabilities = ast_format_cap_alloc())) { 02762 return AST_MODULE_LOAD_FAILURE; 02763 } 02764 ast_format_cap_add_all(record_tech.capabilities); 02765 if (ast_channel_register(&record_tech)) { 02766 ast_log(LOG_ERROR, "Unable to register ConfBridge recorder.\n"); 02767 return AST_MODULE_LOAD_FAILURE; 02768 } 02769 /* Create a container to hold the conference bridges */ 02770 if (!(conference_bridges = ao2_container_alloc(CONFERENCE_BRIDGE_BUCKETS, conference_bridge_hash_cb, conference_bridge_cmp_cb))) { 02771 return AST_MODULE_LOAD_FAILURE; 02772 } 02773 if (ast_register_application_xml(app, confbridge_exec)) { 02774 ao2_ref(conference_bridges, -1); 02775 return AST_MODULE_LOAD_FAILURE; 02776 } 02777 02778 res |= ast_cli_register_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry)); 02779 res |= ast_manager_register_xml("ConfbridgeList", EVENT_FLAG_REPORTING, action_confbridgelist); 02780 res |= ast_manager_register_xml("ConfbridgeListRooms", EVENT_FLAG_REPORTING, action_confbridgelistrooms); 02781 res |= ast_manager_register_xml("ConfbridgeMute", EVENT_FLAG_CALL, action_confbridgemute); 02782 res |= ast_manager_register_xml("ConfbridgeUnmute", EVENT_FLAG_CALL, action_confbridgeunmute); 02783 res |= ast_manager_register_xml("ConfbridgeKick", EVENT_FLAG_CALL, action_confbridgekick); 02784 res |= ast_manager_register_xml("ConfbridgeUnlock", EVENT_FLAG_CALL, action_confbridgeunlock); 02785 res |= ast_manager_register_xml("ConfbridgeLock", EVENT_FLAG_CALL, action_confbridgelock); 02786 res |= ast_manager_register_xml("ConfbridgeStartRecord", EVENT_FLAG_CALL, action_confbridgestartrecord); 02787 res |= ast_manager_register_xml("ConfbridgeStopRecord", EVENT_FLAG_CALL, action_confbridgestoprecord); 02788 res |= ast_manager_register_xml("ConfbridgeSetSingleVideoSrc", EVENT_FLAG_CALL, action_confbridgesetsinglevideosrc); 02789 02790 conf_load_config(0); 02791 return res; 02792 }
| static int play_prompt_to_channel | ( | struct conference_bridge * | conference_bridge, | |
| struct ast_channel * | chan, | |||
| const char * | file | |||
| ) | [static] |
Play back an audio file to a channel.
| conference_bridge | Conference bridge they are in | |
| chan | Channel to play audio prompt to | |
| file | Prompt to play |
Definition at line 637 of file app_confbridge.c.
References ao2_lock, ao2_unlock, and ast_stream_and_wait().
Referenced by post_join_marked(), and post_join_unmarked().
00638 { 00639 int res; 00640 ao2_unlock(conference_bridge); 00641 res = ast_stream_and_wait(chan, file, ""); 00642 ao2_lock(conference_bridge); 00643 return res; 00644 }
| static int play_sound_file | ( | struct conference_bridge * | conference_bridge, | |
| const char * | filename | |||
| ) | [static] |
Play sound file into conference bridge.
| conference_bridge | The conference bridge to play sound file into | |
| filename | Sound file to play |
| 0 | success | |
| -1 | failure |
Definition at line 1187 of file app_confbridge.c.
References play_sound_helper().
Referenced by announce_user_count(), confbridge_exec(), leave_conference_bridge(), and post_join_marked().
01188 { 01189 return play_sound_helper(conference_bridge, filename, 0); 01190 }
| static int play_sound_helper | ( | struct conference_bridge * | conference_bridge, | |
| const char * | filename, | |||
| int | say_number | |||
| ) | [static] |
Definition at line 1146 of file app_confbridge.c.
References alloc_playback_chan(), ast_bridge_depart(), ast_bridge_impart(), ast_channel_language(), ast_channel_name(), ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_say_number(), ast_stream_and_wait(), ast_strlen_zero(), ast_channel_tech::bridged_channel, and ast_channel::tech.
Referenced by action_toggle_mute_participants(), play_sound_file(), and play_sound_number().
01147 { 01148 struct ast_channel *underlying_channel; 01149 01150 ast_mutex_lock(&conference_bridge->playback_lock); 01151 if (!(conference_bridge->playback_chan)) { 01152 if (alloc_playback_chan(conference_bridge)) { 01153 ast_mutex_unlock(&conference_bridge->playback_lock); 01154 return -1; 01155 } 01156 underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL); 01157 } else { 01158 /* Channel was already available so we just need to add it back into the bridge */ 01159 underlying_channel = conference_bridge->playback_chan->tech->bridged_channel(conference_bridge->playback_chan, NULL); 01160 ast_bridge_impart(conference_bridge->bridge, underlying_channel, NULL, NULL, 0); 01161 } 01162 01163 /* The channel is all under our control, in goes the prompt */ 01164 if (!ast_strlen_zero(filename)) { 01165 ast_stream_and_wait(conference_bridge->playback_chan, filename, ""); 01166 } else { 01167 ast_say_number(conference_bridge->playback_chan, say_number, "", ast_channel_language(conference_bridge->playback_chan), NULL); 01168 } 01169 01170 ast_debug(1, "Departing underlying channel '%s' from bridge '%p'\n", ast_channel_name(underlying_channel), conference_bridge->bridge); 01171 ast_bridge_depart(conference_bridge->bridge, underlying_channel); 01172 01173 ast_mutex_unlock(&conference_bridge->playback_lock); 01174 01175 return 0; 01176 }
| static int play_sound_number | ( | struct conference_bridge * | conference_bridge, | |
| int | say_number | |||
| ) | [static] |
Play number into the conference bridge.
| 0 | success | |
| -1 | failure |
Definition at line 1201 of file app_confbridge.c.
References play_sound_helper().
Referenced by announce_user_count().
01202 { 01203 return play_sound_helper(conference_bridge, NULL, say_number); 01204 }
| static int post_join_marked | ( | struct conference_bridge * | conference_bridge, | |
| struct conference_bridge_user * | conference_bridge_user | |||
| ) | [static] |
Perform post-joining marked specific actions.
| conference_bridge | Conference bridge being joined | |
| conference_bridge_user | Conference bridge user joining |
Definition at line 723 of file app_confbridge.c.
References ao2_lock, ao2_unlock, ast_autoservice_start(), ast_autoservice_stop(), ast_bridge_suspend(), ast_bridge_unsuspend(), AST_LIST_TRAVERSE, ast_moh_start(), ast_moh_stop(), ast_test_flag, conf_get_sound(), play_prompt_to_channel(), and play_sound_file().
Referenced by join_conference_bridge().
00724 { 00725 if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MARKEDUSER)) { 00726 struct conference_bridge_user *other_conference_bridge_user = NULL; 00727 00728 /* If we are not the first user to join, then the users are already 00729 * in the conference so we do not need to update them. */ 00730 if (conference_bridge->markedusers >= 2) { 00731 return 0; 00732 } 00733 00734 /* Iterate through every participant stopping MOH on them if need be */ 00735 AST_LIST_TRAVERSE(&conference_bridge->users_list, other_conference_bridge_user, list) { 00736 if (other_conference_bridge_user == conference_bridge_user) { 00737 continue; 00738 } 00739 if (other_conference_bridge_user->playing_moh && !ast_bridge_suspend(conference_bridge->bridge, other_conference_bridge_user->chan)) { 00740 other_conference_bridge_user->playing_moh = 0; 00741 ast_moh_stop(other_conference_bridge_user->chan); 00742 ast_bridge_unsuspend(conference_bridge->bridge, other_conference_bridge_user->chan); 00743 } 00744 } 00745 00746 /* Next play the audio file stating they are going to be placed into the conference */ 00747 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) { 00748 ao2_unlock(conference_bridge); 00749 ast_autoservice_start(conference_bridge_user->chan); 00750 play_sound_file(conference_bridge, 00751 conf_get_sound(CONF_SOUND_PLACE_IN_CONF, conference_bridge_user->b_profile.sounds)); 00752 ast_autoservice_stop(conference_bridge_user->chan); 00753 ao2_lock(conference_bridge); 00754 } 00755 00756 /* Finally iterate through and unmute them all */ 00757 AST_LIST_TRAVERSE(&conference_bridge->users_list, other_conference_bridge_user, list) { 00758 if (other_conference_bridge_user == conference_bridge_user) { 00759 continue; 00760 } 00761 /* only unmute them if they are not supposed to start muted */ 00762 if (!ast_test_flag(&other_conference_bridge_user->u_profile, USER_OPT_STARTMUTED)) { 00763 other_conference_bridge_user->features.mute = 0; 00764 } 00765 } 00766 } else { 00767 /* If a marked user already exists in the conference bridge we can just bail out now */ 00768 if (conference_bridge->markedusers) { 00769 return 0; 00770 } 00771 /* Be sure we are muted so we can't talk to anybody else waiting */ 00772 conference_bridge_user->features.mute = 1; 00773 /* If we have not been quieted play back that they are waiting for the leader */ 00774 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET)) { 00775 if (play_prompt_to_channel(conference_bridge, 00776 conference_bridge_user->chan, 00777 conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, conference_bridge_user->b_profile.sounds))) { 00778 /* user hungup while the sound was playing */ 00779 return -1; 00780 } 00781 } 00782 /* Start music on hold if needed */ 00783 /* We need to recheck the markedusers value here. play_prompt_to_channel unlocks the conference bridge, potentially 00784 * allowing a marked user to enter while the prompt was playing 00785 */ 00786 if (!conference_bridge->markedusers && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) { 00787 ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL); 00788 conference_bridge_user->playing_moh = 1; 00789 } 00790 } 00791 return 0; 00792 }
| static int post_join_unmarked | ( | struct conference_bridge * | conference_bridge, | |
| struct conference_bridge_user * | conference_bridge_user | |||
| ) | [static] |
Perform post-joining non-marked specific actions.
| conference_bridge | Conference bridge being joined | |
| conference_bridge_user | Conference bridge user joining |
Definition at line 802 of file app_confbridge.c.
References announce_user_count(), ao2_lock, ao2_unlock, ast_bridge_suspend(), ast_bridge_unsuspend(), AST_LIST_FIRST, ast_moh_start(), ast_moh_stop(), ast_test_flag, conf_get_sound(), and play_prompt_to_channel().
Referenced by join_conference_bridge().
00803 { 00804 /* Play back audio prompt and start MOH if need be if we are the first participant */ 00805 if (conference_bridge->users == 1) { 00806 /* If audio prompts have not been quieted or this prompt quieted play it on out */ 00807 if (!ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_QUIET | USER_OPT_NOONLYPERSON)) { 00808 if (play_prompt_to_channel(conference_bridge, 00809 conference_bridge_user->chan, 00810 conf_get_sound(CONF_SOUND_ONLY_PERSON, conference_bridge_user->b_profile.sounds))) { 00811 /* user hungup while the sound was playing */ 00812 return -1; 00813 } 00814 } 00815 /* If we need to start music on hold on the channel do so now */ 00816 /* We need to re-check the number of users in the conference bridge here because another conference bridge 00817 * participant could have joined while the above prompt was playing for the first user. 00818 */ 00819 if (conference_bridge->users == 1 && ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_MUSICONHOLD)) { 00820 ast_moh_start(conference_bridge_user->chan, conference_bridge_user->u_profile.moh_class, NULL); 00821 conference_bridge_user->playing_moh = 1; 00822 } 00823 return 0; 00824 } 00825 00826 /* Announce number of users if need be */ 00827 if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) { 00828 ao2_unlock(conference_bridge); 00829 if (announce_user_count(conference_bridge, conference_bridge_user)) { 00830 ao2_lock(conference_bridge); 00831 return -1; 00832 } 00833 ao2_lock(conference_bridge); 00834 } 00835 00836 /* If we are the second participant we may need to stop music on hold on the first */ 00837 if (conference_bridge->users == 2) { 00838 struct conference_bridge_user *first_participant = AST_LIST_FIRST(&conference_bridge->users_list); 00839 00840 /* Temporarily suspend the above participant from the bridge so we have control to stop MOH if needed */ 00841 if (ast_test_flag(&first_participant->u_profile, USER_OPT_MUSICONHOLD) && !ast_bridge_suspend(conference_bridge->bridge, first_participant->chan)) { 00842 first_participant->playing_moh = 0; 00843 ast_moh_stop(first_participant->chan); 00844 ast_bridge_unsuspend(conference_bridge->bridge, first_participant->chan); 00845 } 00846 } 00847 00848 if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) && 00849 (conference_bridge->users > conference_bridge_user->u_profile.announce_user_count_all_after)) { 00850 ao2_unlock(conference_bridge); 00851 if (announce_user_count(conference_bridge, NULL)) { 00852 ao2_lock(conference_bridge); 00853 return -1; 00854 } 00855 ao2_lock(conference_bridge); 00856 } 00857 return 0; 00858 }
| static struct ast_frame* rec_read | ( | struct ast_channel * | ast | ) | [static, read] |
Definition at line 353 of file app_confbridge.c.
References ast_null_frame.
00354 { 00355 return &ast_null_frame; 00356 }
| static struct ast_channel * rec_request | ( | const char * | type, | |
| struct ast_format_cap * | cap, | |||
| const struct ast_channel * | requestor, | |||
| const char * | data, | |||
| int * | cause | |||
| ) | [static, read] |
Definition at line 369 of file app_confbridge.c.
References ast_channel_alloc, ast_format_cap_add_all(), ast_format_copy(), ast_format_set(), AST_FORMAT_SLINEAR, ast_random(), AST_STATE_UP, ast_channel::nativeformats, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::tech, and ast_channel::writeformat.
00370 { 00371 struct ast_channel *tmp; 00372 struct ast_format fmt; 00373 const char *conf_name = data; 00374 if (!(tmp = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", NULL, 0, 00375 "ConfBridgeRecorder/conf-%s-uid-%d", 00376 conf_name, 00377 (int) ast_random()))) { 00378 return NULL; 00379 } 00380 ast_format_set(&fmt, AST_FORMAT_SLINEAR, 0); 00381 tmp->tech = &record_tech; 00382 ast_format_cap_add_all(tmp->nativeformats); 00383 ast_format_copy(&tmp->writeformat, &fmt); 00384 ast_format_copy(&tmp->rawwriteformat, &fmt); 00385 ast_format_copy(&tmp->readformat, &fmt); 00386 ast_format_copy(&tmp->rawreadformat, &fmt); 00387 return tmp; 00388 }
| static int rec_write | ( | struct ast_channel * | ast, | |
| struct ast_frame * | f | |||
| ) | [static] |
| static void* record_thread | ( | void * | obj | ) | [static] |
Definition at line 390 of file app_confbridge.c.
References ao2_lock, ao2_ref, ao2_unlock, ast_answer(), ast_bridge_join(), ast_channel_ref, ast_hangup(), AST_PTHREADT_NULL, ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_strlen_zero(), pbx_exec(), and pbx_findapp().
Referenced by conf_start_record().
00391 { 00392 struct conference_bridge *conference_bridge = obj; 00393 struct ast_app *mixmonapp = pbx_findapp("MixMonitor"); 00394 struct ast_channel *chan; 00395 struct ast_str *filename = ast_str_alloca(PATH_MAX); 00396 00397 if (!mixmonapp) { 00398 ao2_ref(conference_bridge, -1); 00399 return NULL; 00400 } 00401 00402 ao2_lock(conference_bridge); 00403 if (!(conference_bridge->record_chan)) { 00404 conference_bridge->record_thread = AST_PTHREADT_NULL; 00405 ao2_unlock(conference_bridge); 00406 ao2_ref(conference_bridge, -1); 00407 return NULL; 00408 } 00409 chan = ast_channel_ref(conference_bridge->record_chan); 00410 00411 if (!(ast_strlen_zero(conference_bridge->b_profile.rec_file))) { 00412 ast_str_append(&filename, 0, "%s", conference_bridge->b_profile.rec_file); 00413 } else { 00414 time_t now; 00415 time(&now); 00416 ast_str_append(&filename, 0, "confbridge-%s-%u.wav", 00417 conference_bridge->name, 00418 (unsigned int) now); 00419 } 00420 ao2_unlock(conference_bridge); 00421 00422 ast_answer(chan); 00423 pbx_exec(chan, mixmonapp, ast_str_buffer(filename)); 00424 ast_bridge_join(conference_bridge->bridge, chan, NULL, NULL, NULL); 00425 00426 ao2_lock(conference_bridge); 00427 conference_bridge->record_thread = AST_PTHREADT_NULL; 00428 ao2_unlock(conference_bridge); 00429 00430 ast_hangup(chan); /* This will eat this threads reference to the channel as well */ 00431 ao2_ref(conference_bridge, -1); 00432 return NULL; 00433 }
| static int reload | ( | void | ) | [static] |
| static void send_conf_end_event | ( | const char * | conf_name | ) | [static] |
Definition at line 535 of file app_confbridge.c.
References EVENT_FLAG_CALL, and manager_event.
Referenced by leave_conference_bridge().
00536 { 00537 manager_event(EVENT_FLAG_CALL, "ConfbridgeEnd", "Conference: %s\r\n", conf_name); 00538 }
| static void send_conf_start_event | ( | const char * | conf_name | ) | [static] |
Definition at line 530 of file app_confbridge.c.
References EVENT_FLAG_CALL, and manager_event.
Referenced by join_conference_bridge().
00531 { 00532 manager_event(EVENT_FLAG_CALL, "ConfbridgeStart", "Conference: %s\r\n", conf_name); 00533 }
| static void send_join_event | ( | struct ast_channel * | chan, | |
| const char * | conf_name | |||
| ) | [static] |
Definition at line 540 of file app_confbridge.c.
References ast_channel_name(), ast_channel_uniqueid(), ast_manager_event, ast_channel::caller, EVENT_FLAG_CALL, ast_party_caller::id, ast_party_id::name, ast_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
Referenced by confbridge_exec().
00541 { 00542 ast_manager_event(chan, EVENT_FLAG_CALL, "ConfbridgeJoin", 00543 "Channel: %s\r\n" 00544 "Uniqueid: %s\r\n" 00545 "Conference: %s\r\n" 00546 "CallerIDnum: %s\r\n" 00547 "CallerIDname: %s\r\n", 00548 ast_channel_name(chan), 00549 ast_channel_uniqueid(chan), 00550 conf_name, 00551 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<unknown>"), 00552 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>") 00553 ); 00554 }
| static void send_leave_event | ( | struct ast_channel * | chan, | |
| const char * | conf_name | |||
| ) | [static] |
Definition at line 556 of file app_confbridge.c.
References ast_channel_name(), ast_channel_uniqueid(), ast_manager_event, ast_channel::caller, EVENT_FLAG_CALL, ast_party_caller::id, ast_party_id::name, ast_party_id::number, S_COR, ast_party_name::str, ast_party_number::str, ast_party_name::valid, and ast_party_number::valid.
Referenced by confbridge_exec().
00557 { 00558 ast_manager_event(chan, EVENT_FLAG_CALL, "ConfbridgeLeave", 00559 "Channel: %s\r\n" 00560 "Uniqueid: %s\r\n" 00561 "Conference: %s\r\n" 00562 "CallerIDnum: %s\r\n" 00563 "CallerIDname: %s\r\n", 00564 ast_channel_name(chan), 00565 ast_channel_uniqueid(chan), 00566 conf_name, 00567 S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, "<unknown>"), 00568 S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, "<unknown>") 00569 ); 00570 }
| static int unload_module | ( | void | ) | [static] |
Called when module is being unloaded.
Definition at line 2721 of file app_confbridge.c.
References ao2_ref, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_format_cap_destroy(), ast_manager_unregister(), ast_unregister_application(), and ast_channel_tech::capabilities.
02722 { 02723 int res = ast_unregister_application(app); 02724 02725 ast_custom_function_unregister(&confbridge_function); 02726 ast_custom_function_unregister(&confbridge_info_function); 02727 02728 ast_cli_unregister_multiple(cli_confbridge, sizeof(cli_confbridge) / sizeof(struct ast_cli_entry)); 02729 02730 /* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */ 02731 ao2_ref(conference_bridges, -1); 02732 02733 conf_destroy_config(); 02734 02735 ast_channel_unregister(&record_tech); 02736 record_tech.capabilities = ast_format_cap_destroy(record_tech.capabilities); 02737 02738 res |= ast_manager_unregister("ConfbridgeList"); 02739 res |= ast_manager_unregister("ConfbridgeListRooms"); 02740 res |= ast_manager_unregister("ConfbridgeMute"); 02741 res |= ast_manager_unregister("ConfbridgeUnmute"); 02742 res |= ast_manager_unregister("ConfbridgeKick"); 02743 res |= ast_manager_unregister("ConfbridgeUnlock"); 02744 res |= ast_manager_unregister("ConfbridgeLock"); 02745 res |= ast_manager_unregister("ConfbridgeStartRecord"); 02746 res |= ast_manager_unregister("ConfbridgeStopRecord"); 02747 02748 return res; 02749 }
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, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, } [static] |
Definition at line 2804 of file app_confbridge.c.
const char app[] = "ConfBridge" [static] |
Definition at line 271 of file app_confbridge.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 2804 of file app_confbridge.c.
struct ast_cli_entry cli_confbridge[] [static] |
Definition at line 2277 of file app_confbridge.c.
struct ast_custom_function confbridge_function [static] |
Initial value:
{
.name = "CONFBRIDGE",
.write = func_confbridge_helper,
}
Definition at line 2287 of file app_confbridge.c.
struct ast_custom_function confbridge_info_function [static] |
Initial value:
{
.name = "CONFBRIDGE_INFO",
.read = func_confbridge_info,
}
Definition at line 2293 of file app_confbridge.c.
struct ao2_container* conference_bridges [static] |
Container to hold all conference bridges in progress.
Definition at line 277 of file app_confbridge.c.
struct ast_channel_tech record_tech [static] |
Definition at line 362 of file app_confbridge.c.
1.5.6