#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <zaptel.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/options.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "enter.h"
#include "leave.h"
Include dependency graph for app_meetme.c:
Go to the source code of this file.
Defines | |
#define | ADMINFLAG_KICKME (1 << 2) |
#define | ADMINFLAG_MUTED (1 << 1) |
#define | CONF_COMMANDS 6 |
#define | CONF_SIZE 320 |
#define | CONFFLAG_ADMIN (1 << 1) |
#define | CONFFLAG_AGI (1 << 8) |
#define | CONFFLAG_ALWAYSPROMPT (1 << 21) |
#define | CONFFLAG_ANNOUNCEUSERCOUNT (1 << 7) |
#define | CONFFLAG_DYNAMIC (1 << 17) |
#define | CONFFLAG_DYNAMICPIN (1 << 18) |
#define | CONFFLAG_EMPTY (1 << 19) |
#define | CONFFLAG_EMPTYNOPIN (1 << 20) |
#define | CONFFLAG_EXIT_CONTEXT (1 << 12) |
#define | CONFFLAG_INTROUSER (1 << 14) |
#define | CONFFLAG_MARKEDEXIT (1 << 10) |
#define | CONFFLAG_MARKEDUSER (1 << 13) |
#define | CONFFLAG_MOH (1 << 9) |
#define | CONFFLAG_MONITOR (1 << 2) |
#define | CONFFLAG_MONITORTALKER (1 << 16) |
#define | CONFFLAG_POUNDEXIT (1 << 3) |
#define | CONFFLAG_QUIET (1 << 6) |
#define | CONFFLAG_RECORDCONF (1<< 15) |
#define | CONFFLAG_STARMENU (1 << 4) |
#define | CONFFLAG_TALKER (1 << 5) |
#define | CONFFLAG_WAITMARKED (1 << 11) |
#define | CONFIG_FILE_NAME "meetme.conf" |
#define | DEFAULT_AUDIO_BUFFERS 32 |
#define | ENTER 0 |
#define | LEAVE 1 |
#define | MEETME_DELAYDETECTENDTALK 1000 |
#define | MEETME_DELAYDETECTTALK 300 |
#define | MEETME_RECORD_ACTIVE 1 |
#define | MEETME_RECORD_OFF 0 |
#define | MEETME_RECORD_TERMINATE 2 |
Enumerations | |
enum | volume_action { VOL_UP, VOL_DOWN } |
Functions | |
static int | admin_exec (struct ast_channel *chan, void *data) |
AST_APP_OPTIONS (meetme_opts,{AST_APP_OPTION('a', CONFFLAG_ADMIN), AST_APP_OPTION('c', CONFFLAG_ANNOUNCEUSERCOUNT), AST_APP_OPTION('T', CONFFLAG_MONITORTALKER), AST_APP_OPTION('i', CONFFLAG_INTROUSER), AST_APP_OPTION('m', CONFFLAG_MONITOR), AST_APP_OPTION('p', CONFFLAG_POUNDEXIT), AST_APP_OPTION('s', CONFFLAG_STARMENU), AST_APP_OPTION('t', CONFFLAG_TALKER), AST_APP_OPTION('q', CONFFLAG_QUIET), AST_APP_OPTION('M', CONFFLAG_MOH), AST_APP_OPTION('x', CONFFLAG_MARKEDEXIT), AST_APP_OPTION('X', CONFFLAG_EXIT_CONTEXT), AST_APP_OPTION('A', CONFFLAG_MARKEDUSER), AST_APP_OPTION('b', CONFFLAG_AGI), AST_APP_OPTION('w', CONFFLAG_WAITMARKED), AST_APP_OPTION('r', CONFFLAG_RECORDCONF), AST_APP_OPTION('d', CONFFLAG_DYNAMIC), AST_APP_OPTION('D', CONFFLAG_DYNAMICPIN), AST_APP_OPTION('e', CONFFLAG_EMPTY), AST_APP_OPTION('E', CONFFLAG_EMPTYNOPIN), AST_APP_OPTION('P', CONFFLAG_ALWAYSPROMPT),}) | |
AST_MUTEX_DEFINE_STATIC (conflock) | |
static struct ast_conference * | build_conf (char *confno, char *pin, char *pinadmin, int make, int dynamic) |
static int | careful_write (int fd, unsigned char *data, int len, int block) |
static char * | complete_confcmd (char *line, char *word, int pos, int state) |
static int | conf_cmd (int fd, int argc, char **argv) |
static int | conf_exec (struct ast_channel *chan, void *data) |
static void | conf_flush (int fd, struct ast_channel *chan) |
static int | conf_free (struct ast_conference *conf) |
static void | conf_play (struct ast_channel *chan, struct ast_conference *conf, int sound) |
static int | conf_run (struct ast_channel *chan, struct ast_conference *conf, int confflags) |
static int | confs_show (int fd, int argc, char **argv) |
static int | count_exec (struct ast_channel *chan, void *data) |
char * | description (void) |
Provides a description of the module. | |
static struct ast_conference * | find_conf (struct ast_channel *chan, char *confno, int make, int dynamic, char *dynamic_pin, struct ast_flags *confflags) |
static struct ast_conf_user * | find_user (struct ast_conference *conf, char *callerident) |
static char * | istalking (int x) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
static void | load_config (void) |
int | load_module (void) |
Initialize the module. | |
static void * | recordthread (void *args) |
int | reload (void) |
Reload stuff. | |
static void | reset_volumes (struct ast_conf_user *user) |
static int | set_listen_volume (struct ast_conf_user *user, int volume) |
static int | set_talk_volume (struct ast_conf_user *user, int volume) |
static void | tweak_listen_volume (struct ast_conf_user *user, enum volume_action action) |
static void | tweak_talk_volume (struct ast_conf_user *user, enum volume_action action) |
static void | tweak_volume (struct volume *vol, enum volume_action action) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static const char * | app = "MeetMe" |
static const char * | app2 = "MeetMeCount" |
static const char * | app3 = "MeetMeAdmin" |
static int | audio_buffers |
static struct ast_cli_entry | cli_conf |
static struct ast_cli_entry | cli_show_confs |
static char | conf_usage [] |
static struct ast_conference * | confs |
static const char * | descrip |
static const char * | descrip2 |
static const char * | descrip3 |
static signed char | gain_map [] |
LOCAL_USER_DECL | |
static char | show_confs_usage [] |
STANDARD_LOCAL_USER | |
static const char * | synopsis = "MeetMe conference bridge" |
static const char * | synopsis2 = "MeetMe participant count" |
static const char * | synopsis3 = "MeetMe conference Administration" |
static const char * | tdesc = "MeetMe conference bridge" |
Definition in file app_meetme.c.
|
Definition at line 181 of file app_meetme.c. Referenced by admin_exec(), and conf_run(). |
|
Definition at line 180 of file app_meetme.c. Referenced by admin_exec(), conf_cmd(), and conf_run(). |
|
Referenced by complete_confcmd(). |
|
Definition at line 206 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 208 of file app_meetme.c. Referenced by admin_exec(), conf_cmd(), conf_exec(), and conf_run(). |
|
Definition at line 215 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 228 of file app_meetme.c. Referenced by conf_exec(). |
|
Definition at line 214 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 224 of file app_meetme.c. Referenced by conf_exec(). |
|
Definition at line 225 of file app_meetme.c. Referenced by conf_exec(). |
|
Definition at line 226 of file app_meetme.c. Referenced by conf_exec(). |
|
Definition at line 227 of file app_meetme.c. Referenced by conf_exec(). |
|
Definition at line 219 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 221 of file app_meetme.c. Referenced by conf_run(), and find_conf(). |
|
Definition at line 217 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 220 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 216 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 209 of file app_meetme.c. Referenced by conf_cmd(), and conf_run(). |
|
Definition at line 223 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 210 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 213 of file app_meetme.c. Referenced by conf_run(), and find_conf(). |
|
Definition at line 222 of file app_meetme.c. Referenced by conf_run(), and find_conf(). |
|
Definition at line 211 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 212 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 218 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 125 of file app_meetme.c. Referenced by conf_exec(), find_conf(), and load_config(). |
|
Definition at line 178 of file app_meetme.c. Referenced by load_config(). |
|
Definition at line 199 of file app_meetme.c. Referenced by conf_play(), and conf_run(). |
|
Definition at line 200 of file app_meetme.c. Referenced by conf_play(), and conf_run(). |
|
Definition at line 183 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 182 of file app_meetme.c. Referenced by conf_run(). |
|
Definition at line 203 of file app_meetme.c. Referenced by conf_free(), conf_run(), and recordthread(). |
|
Definition at line 202 of file app_meetme.c. Referenced by conf_free(), and recordthread(). |
|
Definition at line 204 of file app_meetme.c. Referenced by conf_free(), and recordthread(). |
|
Definition at line 185 of file app_meetme.c.
|
|
Definition at line 2040 of file app_meetme.c. References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ast_conf_user::adminflags, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_strlen_zero(), CONFFLAG_ADMIN, ast_conference::confno, confs, find_user(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_NOTICE, LOG_WARNING, ast_conference::next, ast_conf_user::nextuser, strsep(), user, and ast_conf_user::userflags. Referenced by conf_cmd(), and load_module(). 02040 { 02041 char *params, *command = NULL, *caller = NULL, *conf = NULL; 02042 struct ast_conference *cnf; 02043 struct ast_conf_user *user = NULL; 02044 struct localuser *u; 02045 02046 LOCAL_USER_ADD(u); 02047 02048 ast_mutex_lock(&conflock); 02049 /* The param has the conference number the user and the command to execute */ 02050 if (!ast_strlen_zero(data)) { 02051 params = ast_strdupa((char *) data); 02052 conf = strsep(¶ms, "|"); 02053 command = strsep(¶ms, "|"); 02054 caller = strsep(¶ms, "|"); 02055 02056 if (!command) { 02057 ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n"); 02058 ast_mutex_unlock(&conflock); 02059 LOCAL_USER_REMOVE(u); 02060 return -1; 02061 } 02062 for (cnf = confs; cnf; cnf = cnf->next) { 02063 if (!strcmp(cnf->confno, conf)) 02064 break; 02065 } 02066 02067 if (caller) 02068 user = find_user(cnf, caller); 02069 02070 if (cnf) { 02071 switch((int) (*command)) { 02072 case 76: /* L: Lock */ 02073 cnf->locked = 1; 02074 break; 02075 case 108: /* l: Unlock */ 02076 cnf->locked = 0; 02077 break; 02078 case 75: /* K: kick all users*/ 02079 user = cnf->firstuser; 02080 while(user) { 02081 user->adminflags |= ADMINFLAG_KICKME; 02082 if (user->nextuser) { 02083 user = user->nextuser; 02084 } else { 02085 break; 02086 } 02087 } 02088 break; 02089 case 101: /* e: Eject last user*/ 02090 user = cnf->lastuser; 02091 if (!(user->userflags & CONFFLAG_ADMIN)) { 02092 user->adminflags |= ADMINFLAG_KICKME; 02093 break; 02094 } else 02095 ast_log(LOG_NOTICE, "Not kicking last user, is an Admin!\n"); 02096 break; 02097 case 77: /* M: Mute */ 02098 if (user) { 02099 user->adminflags |= ADMINFLAG_MUTED; 02100 } else { 02101 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02102 } 02103 break; 02104 case 78: /* N: Mute all users */ 02105 user = cnf->firstuser; 02106 while(user) { 02107 if (user && !(user->userflags & CONFFLAG_ADMIN)) 02108 user->adminflags |= ADMINFLAG_MUTED; 02109 if (user->nextuser) { 02110 user = user->nextuser; 02111 } else { 02112 break; 02113 } 02114 } 02115 break; 02116 case 109: /* m: Unmute */ 02117 if (user && (user->adminflags & ADMINFLAG_MUTED)) { 02118 user->adminflags ^= ADMINFLAG_MUTED; 02119 } else { 02120 ast_log(LOG_NOTICE, "Specified User not found or he muted himself!\n"); 02121 } 02122 break; 02123 case 110: /* n: Unmute all users */ 02124 user = cnf->firstuser; 02125 while(user) { 02126 if (user && (user-> adminflags & ADMINFLAG_MUTED)) { 02127 user->adminflags ^= ADMINFLAG_MUTED; 02128 } 02129 if (user->nextuser) { 02130 user = user->nextuser; 02131 } else { 02132 break; 02133 } 02134 } 02135 break; 02136 case 107: /* k: Kick user */ 02137 if (user) { 02138 user->adminflags |= ADMINFLAG_KICKME; 02139 } else { 02140 ast_log(LOG_NOTICE, "Specified User not found!\n"); 02141 } 02142 break; 02143 } 02144 } else { 02145 ast_log(LOG_NOTICE, "Conference Number not found\n"); 02146 } 02147 } 02148 ast_mutex_unlock(&conflock); 02149 02150 LOCAL_USER_REMOVE(u); 02151 02152 return 0; 02153 }
|
|
|
|
|
|
Definition at line 436 of file app_meetme.c. References AST_FORMAT_ULAW, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), ast_verbose(), calloc, ast_conference::confno, confs, free, LOG_WARNING, ast_conference::next, option_verbose, and VERBOSE_PREFIX_3. Referenced by find_conf(). 00437 { 00438 struct ast_conference *cnf; 00439 struct zt_confinfo ztc; 00440 00441 ast_mutex_lock(&conflock); 00442 00443 for (cnf = confs; cnf; cnf = cnf->next) { 00444 if (!strcmp(confno, cnf->confno)) 00445 break; 00446 } 00447 00448 if (!cnf && (make || dynamic)) { 00449 /* Make a new one */ 00450 cnf = calloc(1, sizeof(*cnf)); 00451 if (cnf) { 00452 ast_copy_string(cnf->confno, confno, sizeof(cnf->confno)); 00453 ast_copy_string(cnf->pin, pin, sizeof(cnf->pin)); 00454 ast_copy_string(cnf->pinadmin, pinadmin, sizeof(cnf->pinadmin)); 00455 cnf->markedusers = 0; 00456 cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo", NULL); 00457 if (cnf->chan) { 00458 cnf->fd = cnf->chan->fds[0]; /* for use by conf_play() */ 00459 } else { 00460 ast_log(LOG_WARNING, "Unable to open pseudo channel - trying device\n"); 00461 cnf->fd = open("/dev/zap/pseudo", O_RDWR); 00462 if (cnf->fd < 0) { 00463 ast_log(LOG_WARNING, "Unable to open pseudo device\n"); 00464 free(cnf); 00465 cnf = NULL; 00466 goto cnfout; 00467 } 00468 } 00469 memset(&ztc, 0, sizeof(ztc)); 00470 /* Setup a new zap conference */ 00471 ztc.chan = 0; 00472 ztc.confno = -1; 00473 ztc.confmode = ZT_CONF_CONFANN | ZT_CONF_CONFANNMON; 00474 if (ioctl(cnf->fd, ZT_SETCONF, &ztc)) { 00475 ast_log(LOG_WARNING, "Error setting conference\n"); 00476 if (cnf->chan) 00477 ast_hangup(cnf->chan); 00478 else 00479 close(cnf->fd); 00480 free(cnf); 00481 cnf = NULL; 00482 goto cnfout; 00483 } 00484 /* Fill the conference struct */ 00485 cnf->start = time(NULL); 00486 cnf->zapconf = ztc.confno; 00487 cnf->isdynamic = dynamic; 00488 cnf->firstuser = NULL; 00489 cnf->lastuser = NULL; 00490 cnf->locked = 0; 00491 if (option_verbose > 2) 00492 ast_verbose(VERBOSE_PREFIX_3 "Created MeetMe conference %d for conference '%s'\n", cnf->zapconf, cnf->confno); 00493 cnf->next = confs; 00494 confs = cnf; 00495 } else 00496 ast_log(LOG_WARNING, "Out of memory\n"); 00497 } 00498 cnfout: 00499 ast_mutex_unlock(&conflock); 00500 return cnf; 00501 }
|
|
Definition at line 265 of file app_meetme.c. References ast_log(), and LOG_WARNING. Referenced by conf_play(), and conf_run(). 00266 { 00267 int res; 00268 int x; 00269 00270 while (len) { 00271 if (block) { 00272 x = ZT_IOMUX_WRITE | ZT_IOMUX_SIGEVENT; 00273 res = ioctl(fd, ZT_IOMUX, &x); 00274 } else 00275 res = 0; 00276 if (res >= 0) 00277 res = write(fd, data, len); 00278 if (res < 1) { 00279 if (errno != EAGAIN) { 00280 ast_log(LOG_WARNING, "Failed to write audio data to conference: %s\n", strerror(errno)); 00281 return -1; 00282 } else 00283 return 0; 00284 } 00285 len -= res; 00286 data += res; 00287 } 00288 00289 return 0; 00290 }
|
|
Definition at line 643 of file app_meetme.c. References ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, CONF_COMMANDS, ast_conference::confno, confs, ast_conference::firstuser, ast_conference::next, ast_conf_user::nextuser, strdup, strsep(), and ast_conf_user::user_no. 00643 { 00644 #define CONF_COMMANDS 6 00645 int which = 0, x = 0; 00646 struct ast_conference *cnf = NULL; 00647 struct ast_conf_user *usr = NULL; 00648 char *confno = NULL; 00649 char usrno[50] = ""; 00650 char cmds[CONF_COMMANDS][20] = {"lock", "unlock", "mute", "unmute", "kick", "list"}; 00651 char *myline; 00652 00653 if (pos == 1) { 00654 /* Command */ 00655 for (x = 0;x < CONF_COMMANDS; x++) { 00656 if (!strncasecmp(cmds[x], word, strlen(word))) { 00657 if (++which > state) { 00658 return strdup(cmds[x]); 00659 } 00660 } 00661 } 00662 } else if (pos == 2) { 00663 /* Conference Number */ 00664 ast_mutex_lock(&conflock); 00665 cnf = confs; 00666 while(cnf) { 00667 if (!strncasecmp(word, cnf->confno, strlen(word))) { 00668 if (++which > state) 00669 break; 00670 } 00671 cnf = cnf->next; 00672 } 00673 ast_mutex_unlock(&conflock); 00674 return cnf ? strdup(cnf->confno) : NULL; 00675 } else if (pos == 3) { 00676 /* User Number || Conf Command option*/ 00677 if (strstr(line, "mute") || strstr(line, "kick")) { 00678 if ((state == 0) && (strstr(line, "kick") || strstr(line,"mute")) && !(strncasecmp(word, "all", strlen(word)))) { 00679 return strdup("all"); 00680 } 00681 which++; 00682 ast_mutex_lock(&conflock); 00683 00684 /* TODO: Find the conf number from the cmdline (ignore spaces) <- test this and make it fail-safe! */ 00685 myline = ast_strdupa(line); 00686 if (strsep(&myline, " ") && strsep(&myline, " ") && !confno) { 00687 while((confno = strsep(&myline, " ")) && (strcmp(confno, " ") == 0)) 00688 ; 00689 } 00690 00691 for (cnf = confs; cnf; cnf = cnf->next) { 00692 if (!strcmp(confno, cnf->confno)) 00693 break; 00694 } 00695 00696 if (cnf) { 00697 /* Search for the user */ 00698 for (usr = cnf->firstuser; usr; usr = usr->nextuser) { 00699 snprintf(usrno, sizeof(usrno), "%d", usr->user_no); 00700 if (!strncasecmp(word, usrno, strlen(word))) { 00701 if (++which > state) 00702 break; 00703 } 00704 } 00705 } 00706 ast_mutex_unlock(&conflock); 00707 return usr ? strdup(usrno) : NULL; 00708 } 00709 } 00710 00711 return NULL; 00712 }
|
|
Definition at line 517 of file app_meetme.c. References admin_exec(), ADMINFLAG_MUTED, ast_conf_user::adminflags, ast_cli(), ast_log(), ast_conf_user::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, CONFFLAG_ADMIN, CONFFLAG_MONITOR, ast_conference::confno, confs, ast_conference::firstuser, ast_conference::isdynamic, istalking(), LOG_DEBUG, ast_conference::markedusers, ast_channel::name, ast_conference::next, ast_conf_user::nextuser, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_conference::start, ast_conf_user::talking, total, user, ast_conf_user::user_no, ast_conf_user::userflags, and ast_conference::users. 00517 { 00518 /* Process the command */ 00519 struct ast_conference *cnf; 00520 struct ast_conf_user *user; 00521 int hr, min, sec; 00522 int i = 0, total = 0; 00523 time_t now; 00524 char *header_format = "%-14s %-14s %-10s %-8s %-8s\n"; 00525 char *data_format = "%-12.12s %4.4d %4.4s %02d:%02d:%02d %-8s\n"; 00526 char cmdline[1024] = ""; 00527 00528 if (argc > 8) 00529 ast_cli(fd, "Invalid Arguments.\n"); 00530 /* Check for length so no buffer will overflow... */ 00531 for (i = 0; i < argc; i++) { 00532 if (strlen(argv[i]) > 100) 00533 ast_cli(fd, "Invalid Arguments.\n"); 00534 } 00535 if (argc == 1) { 00536 /* 'MeetMe': List all the conferences */ 00537 now = time(NULL); 00538 cnf = confs; 00539 if (!cnf) { 00540 ast_cli(fd, "No active MeetMe conferences.\n"); 00541 return RESULT_SUCCESS; 00542 } 00543 ast_cli(fd, header_format, "Conf Num", "Parties", "Marked", "Activity", "Creation"); 00544 while(cnf) { 00545 if (cnf->markedusers == 0) 00546 strcpy(cmdline, "N/A "); 00547 else 00548 snprintf(cmdline, sizeof(cmdline), "%4.4d", cnf->markedusers); 00549 hr = (now - cnf->start) / 3600; 00550 min = ((now - cnf->start) % 3600) / 60; 00551 sec = (now - cnf->start) % 60; 00552 00553 ast_cli(fd, data_format, cnf->confno, cnf->users, cmdline, hr, min, sec, cnf->isdynamic ? "Dynamic" : "Static"); 00554 00555 total += cnf->users; 00556 cnf = cnf->next; 00557 } 00558 ast_cli(fd, "* Total number of MeetMe users: %d\n", total); 00559 return RESULT_SUCCESS; 00560 } 00561 if (argc < 3) 00562 return RESULT_SHOWUSAGE; 00563 ast_copy_string(cmdline, argv[2], sizeof(cmdline)); /* Argv 2: conference number */ 00564 if (strstr(argv[1], "lock")) { 00565 if (strcmp(argv[1], "lock") == 0) { 00566 /* Lock */ 00567 strncat(cmdline, "|L", sizeof(cmdline) - strlen(cmdline) - 1); 00568 } else { 00569 /* Unlock */ 00570 strncat(cmdline, "|l", sizeof(cmdline) - strlen(cmdline) - 1); 00571 } 00572 } else if (strstr(argv[1], "mute")) { 00573 if (argc < 4) 00574 return RESULT_SHOWUSAGE; 00575 if (strcmp(argv[1], "mute") == 0) { 00576 /* Mute */ 00577 if (strcmp(argv[3], "all") == 0) { 00578 strncat(cmdline, "|N", sizeof(cmdline) - strlen(cmdline) - 1); 00579 } else { 00580 strncat(cmdline, "|M|", sizeof(cmdline) - strlen(cmdline) - 1); 00581 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00582 } 00583 } else { 00584 /* Unmute */ 00585 if (strcmp(argv[3], "all") == 0) { 00586 strncat(cmdline, "|n", sizeof(cmdline) - strlen(cmdline) - 1); 00587 } else { 00588 strncat(cmdline, "|m|", sizeof(cmdline) - strlen(cmdline) - 1); 00589 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00590 } 00591 } 00592 } else if (strcmp(argv[1], "kick") == 0) { 00593 if (argc < 4) 00594 return RESULT_SHOWUSAGE; 00595 if (strcmp(argv[3], "all") == 0) { 00596 /* Kick all */ 00597 strncat(cmdline, "|K", sizeof(cmdline) - strlen(cmdline) - 1); 00598 } else { 00599 /* Kick a single user */ 00600 strncat(cmdline, "|k|", sizeof(cmdline) - strlen(cmdline) - 1); 00601 strncat(cmdline, argv[3], sizeof(cmdline) - strlen(cmdline) - 1); 00602 } 00603 } else if(strcmp(argv[1], "list") == 0) { 00604 /* List all the users in a conference */ 00605 if (!confs) { 00606 ast_cli(fd, "No active conferences.\n"); 00607 return RESULT_SUCCESS; 00608 } 00609 cnf = confs; 00610 /* Find the right conference */ 00611 while(cnf) { 00612 if (strcmp(cnf->confno, argv[2]) == 0) 00613 break; 00614 if (cnf->next) { 00615 cnf = cnf->next; 00616 } else { 00617 ast_cli(fd, "No such conference: %s.\n",argv[2]); 00618 return RESULT_SUCCESS; 00619 } 00620 } 00621 /* Show all the users */ 00622 for (user = cnf->firstuser; user; user = user->nextuser) 00623 ast_cli(fd, "User #: %-2.2d %12.12s %-20.20s Channel: %s %s %s %s %s\n", 00624 user->user_no, 00625 user->chan->cid.cid_num ? user->chan->cid.cid_num : "<unknown>", 00626 user->chan->cid.cid_name ? user->chan->cid.cid_name : "<no name>", 00627 user->chan->name, 00628 user->userflags & CONFFLAG_ADMIN ? "(Admin)" : "", 00629 user->userflags & CONFFLAG_MONITOR ? "(Listen only)" : "", 00630 user->adminflags & ADMINFLAG_MUTED ? "(Admin Muted)" : "", 00631 istalking(user->talking)); 00632 ast_cli(fd,"%d users in that conference.\n",cnf->users); 00633 00634 return RESULT_SUCCESS; 00635 } else 00636 return RESULT_SHOWUSAGE; 00637 ast_log(LOG_DEBUG, "Cmdline: %s\n", cmdline); 00638 admin_exec(NULL, cmdline); 00639 00640 return 0; 00641 }
|
|
Definition at line 1765 of file app_meetme.c. References ast_channel::_state, ast_answer(), ast_app_getdata(), ast_app_parse_options(), ast_config_destroy(), ast_config_load(), AST_DIGIT_ANY, ast_log(), AST_MAX_EXTENSION, ast_mutex_lock(), ast_mutex_unlock(), ast_say_digits(), ast_set_flag, AST_STATE_UP, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_variable_browse(), ast_waitstream(), cfg, conf_free(), conf_run(), CONFFLAG_ADMIN, CONFFLAG_ALWAYSPROMPT, CONFFLAG_DYNAMIC, CONFFLAG_DYNAMICPIN, CONFFLAG_EMPTY, CONFFLAG_EMPTYNOPIN, CONFIG_FILE_NAME, ast_conference::confno, confs, find_conf(), ast_flags::flags, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, ast_conference::next, ast_conference::pin, ast_conference::pinadmin, strsep(), ast_conference::users, ast_variable::value, and var. Referenced by load_module(). 01766 { 01767 int res=-1; 01768 struct localuser *u; 01769 char confno[AST_MAX_EXTENSION] = ""; 01770 int allowretry = 0; 01771 int retrycnt = 0; 01772 struct ast_conference *cnf; 01773 struct ast_flags confflags = {0}; 01774 int dynamic = 0; 01775 int empty = 0, empty_no_pin = 0; 01776 int always_prompt = 0; 01777 char *notdata, *info, *inflags = NULL, *inpin = NULL, the_pin[AST_MAX_EXTENSION] = ""; 01778 01779 LOCAL_USER_ADD(u); 01780 01781 if (ast_strlen_zero(data)) { 01782 allowretry = 1; 01783 notdata = ""; 01784 } else { 01785 notdata = data; 01786 } 01787 01788 if (chan->_state != AST_STATE_UP) 01789 ast_answer(chan); 01790 01791 info = ast_strdupa(notdata); 01792 01793 if (info) { 01794 char *tmp = strsep(&info, "|"); 01795 ast_copy_string(confno, tmp, sizeof(confno)); 01796 if (ast_strlen_zero(confno)) { 01797 allowretry = 1; 01798 } 01799 } 01800 if (info) 01801 inflags = strsep(&info, "|"); 01802 if (info) 01803 inpin = strsep(&info, "|"); 01804 if (inpin) 01805 ast_copy_string(the_pin, inpin, sizeof(the_pin)); 01806 01807 if (inflags) { 01808 ast_app_parse_options(meetme_opts, &confflags, NULL, inflags); 01809 dynamic = ast_test_flag(&confflags, CONFFLAG_DYNAMIC | CONFFLAG_DYNAMICPIN); 01810 if (ast_test_flag(&confflags, CONFFLAG_DYNAMICPIN) && !inpin) 01811 strcpy(the_pin, "q"); 01812 01813 empty = ast_test_flag(&confflags, CONFFLAG_EMPTY | CONFFLAG_EMPTYNOPIN); 01814 empty_no_pin = ast_test_flag(&confflags, CONFFLAG_EMPTYNOPIN); 01815 always_prompt = ast_test_flag(&confflags, CONFFLAG_ALWAYSPROMPT); 01816 } 01817 01818 do { 01819 if (retrycnt > 3) 01820 allowretry = 0; 01821 if (empty) { 01822 int i, map[1024] = { 0, }; 01823 struct ast_config *cfg; 01824 struct ast_variable *var; 01825 int confno_int; 01826 01827 ast_mutex_lock(&conflock); 01828 for (cnf = confs; cnf; cnf = cnf->next) { 01829 if (sscanf(cnf->confno, "%d", &confno_int) == 1) { 01830 /* Disqualify in use conference */ 01831 if (confno_int >= 0 && confno_int < 1024) 01832 map[confno_int]++; 01833 } 01834 } 01835 ast_mutex_unlock(&conflock); 01836 01837 /* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */ 01838 if ((empty_no_pin) || (!dynamic)) { 01839 cfg = ast_config_load(CONFIG_FILE_NAME); 01840 if (cfg) { 01841 var = ast_variable_browse(cfg, "rooms"); 01842 while (var) { 01843 if (!strcasecmp(var->name, "conf")) { 01844 char *stringp = ast_strdupa(var->value); 01845 if (stringp) { 01846 char *confno_tmp = strsep(&stringp, "|,"); 01847 int found = 0; 01848 if (sscanf(confno_tmp, "%d", &confno_int) == 1) { 01849 if ((confno_int >= 0) && (confno_int < 1024)) { 01850 if (stringp && empty_no_pin) { 01851 map[confno_int]++; 01852 } 01853 } 01854 } 01855 if (!dynamic) { 01856 /* For static: run through the list and see if this conference is empty */ 01857 ast_mutex_lock(&conflock); 01858 cnf = confs; 01859 while (cnf) { 01860 if (!strcmp(confno_tmp, cnf->confno)) { 01861 /* The conference exists, therefore it's not empty */ 01862 found = 1; 01863 break; 01864 } 01865 cnf = cnf->next; 01866 } 01867 ast_mutex_unlock(&conflock); 01868 if (!found) { 01869 /* At this point, we have a confno_tmp (static conference) that is empty */ 01870 if ((empty_no_pin && ((!stringp) || (stringp && (stringp[0] == '\0')))) || (!empty_no_pin)) { 01871 /* Case 1: empty_no_pin and pin is nonexistent (NULL) 01872 * Case 2: empty_no_pin and pin is blank (but not NULL) 01873 * Case 3: not empty_no_pin 01874 */ 01875 ast_copy_string(confno, confno_tmp, sizeof(confno)); 01876 break; 01877 /* XXX the map is not complete (but we do have a confno) */ 01878 } 01879 } 01880 } 01881 } else { 01882 ast_log(LOG_ERROR, "Out of memory\n"); 01883 } 01884 } 01885 var = var->next; 01886 } 01887 ast_config_destroy(cfg); 01888 } 01889 } 01890 01891 /* Select first conference number not in use */ 01892 if (ast_strlen_zero(confno) && dynamic) { 01893 for (i = 0; i < sizeof(map) / sizeof(map[0]); i++) { 01894 if (!map[i]) { 01895 snprintf(confno, sizeof(confno), "%d", i); 01896 break; 01897 } 01898 } 01899 } 01900 01901 /* Not found? */ 01902 if (ast_strlen_zero(confno)) { 01903 res = ast_streamfile(chan, "conf-noempty", chan->language); 01904 if (!res) 01905 ast_waitstream(chan, ""); 01906 } else { 01907 if (sscanf(confno, "%d", &confno_int) == 1) { 01908 res = ast_streamfile(chan, "conf-enteringno", chan->language); 01909 if (!res) { 01910 ast_waitstream(chan, ""); 01911 res = ast_say_digits(chan, confno_int, "", chan->language); 01912 } 01913 } else { 01914 ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno); 01915 } 01916 } 01917 } 01918 01919 while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) { 01920 /* Prompt user for conference number */ 01921 res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0); 01922 if (res < 0) { 01923 /* Don't try to validate when we catch an error */ 01924 confno[0] = '\0'; 01925 allowretry = 0; 01926 break; 01927 } 01928 } 01929 if (!ast_strlen_zero(confno)) { 01930 /* Check the validity of the conference */ 01931 cnf = find_conf(chan, confno, 1, dynamic, the_pin, &confflags); 01932 if (!cnf) { 01933 res = ast_streamfile(chan, "conf-invalid", chan->language); 01934 if (!res) 01935 ast_waitstream(chan, ""); 01936 res = -1; 01937 if (allowretry) 01938 confno[0] = '\0'; 01939 } else { 01940 if ((!ast_strlen_zero(cnf->pin) && 01941 !ast_test_flag(&confflags, CONFFLAG_ADMIN)) || 01942 (!ast_strlen_zero(cnf->pinadmin) && 01943 ast_test_flag(&confflags, CONFFLAG_ADMIN))) { 01944 char pin[AST_MAX_EXTENSION]=""; 01945 int j; 01946 01947 /* Allow the pin to be retried up to 3 times */ 01948 for (j = 0; j < 3; j++) { 01949 if (*the_pin && (always_prompt == 0)) { 01950 ast_copy_string(pin, the_pin, sizeof(pin)); 01951 res = 0; 01952 } else { 01953 /* Prompt user for pin if pin is required */ 01954 res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0); 01955 } 01956 if (res >= 0) { 01957 if (!strcasecmp(pin, cnf->pin) || 01958 (!ast_strlen_zero(cnf->pinadmin) && 01959 !strcasecmp(pin, cnf->pinadmin))) { 01960 /* Pin correct */ 01961 allowretry = 0; 01962 if (!ast_strlen_zero(cnf->pinadmin) && !strcasecmp(pin, cnf->pinadmin)) 01963 ast_set_flag(&confflags, CONFFLAG_ADMIN); 01964 /* Run the conference */ 01965 res = conf_run(chan, cnf, confflags.flags); 01966 break; 01967 } else { 01968 /* Pin invalid */ 01969 if (!ast_streamfile(chan, "conf-invalidpin", chan->language)) 01970 res = ast_waitstream(chan, AST_DIGIT_ANY); 01971 else { 01972 ast_log(LOG_WARNING, "Couldn't play invalid pin msg!\n"); 01973 break; 01974 } 01975 if (res < 0) 01976 break; 01977 pin[0] = res; 01978 pin[1] = '\0'; 01979 res = -1; 01980 if (allowretry) 01981 confno[0] = '\0'; 01982 } 01983 } else { 01984 /* failed when getting the pin */ 01985 res = -1; 01986 allowretry = 0; 01987 /* see if we need to get rid of the conference */ 01988 ast_mutex_lock(&conflock); 01989 if (!cnf->users) { 01990 conf_free(cnf); 01991 } 01992 ast_mutex_unlock(&conflock); 01993 break; 01994 } 01995 01996 /* Don't retry pin with a static pin */ 01997 if (*the_pin && (always_prompt==0)) { 01998 break; 01999 } 02000 } 02001 } else { 02002 /* No pin required */ 02003 allowretry = 0; 02004 02005 /* Run the conference */ 02006 res = conf_run(chan, cnf, confflags.flags); 02007 } 02008 } 02009 } 02010 } while (allowretry); 02011 02012 LOCAL_USER_REMOVE(u); 02013 02014 return res; 02015 }
|
|
Definition at line 722 of file app_meetme.c. References ast_frfree(), ast_log(), ast_read(), ast_waitfor(), and LOG_WARNING. Referenced by conf_run(). 00723 { 00724 int x; 00725 00726 /* read any frames that may be waiting on the channel 00727 and throw them away 00728 */ 00729 if (chan) { 00730 struct ast_frame *f; 00731 00732 /* when no frames are available, this will wait 00733 for 1 millisecond maximum 00734 */ 00735 while (ast_waitfor(chan, 1)) { 00736 f = ast_read(chan); 00737 if (f) 00738 ast_frfree(f); 00739 else /* channel was hung up or something else happened */ 00740 break; 00741 } 00742 } 00743 00744 /* flush any data sitting in the pseudo channel */ 00745 x = ZT_FLUSH_ALL; 00746 if (ioctl(fd, ZT_FLUSH, &x)) 00747 ast_log(LOG_WARNING, "Error flushing channel\n"); 00748 00749 }
|
|
Definition at line 753 of file app_meetme.c. References ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_conference::chan, confs, ast_conference::fd, free, LOG_WARNING, MEETME_RECORD_ACTIVE, MEETME_RECORD_OFF, MEETME_RECORD_TERMINATE, ast_conference::next, and ast_conference::recording. Referenced by conf_exec(), and conf_run(). 00754 { 00755 struct ast_conference *prev = NULL, *cur = confs; 00756 00757 while (cur) { 00758 if (cur == conf) { 00759 if (prev) 00760 prev->next = conf->next; 00761 else 00762 confs = conf->next; 00763 break; 00764 } 00765 prev = cur; 00766 cur = cur->next; 00767 } 00768 00769 if (!cur) 00770 ast_log(LOG_WARNING, "Conference not found\n"); 00771 00772 if (conf->recording == MEETME_RECORD_ACTIVE) { 00773 conf->recording = MEETME_RECORD_TERMINATE; 00774 ast_mutex_unlock(&conflock); 00775 while (1) { 00776 ast_mutex_lock(&conflock); 00777 if (conf->recording == MEETME_RECORD_OFF) 00778 break; 00779 ast_mutex_unlock(&conflock); 00780 } 00781 } 00782 00783 if (conf->chan) 00784 ast_hangup(conf->chan); 00785 else 00786 close(conf->fd); 00787 00788 free(conf); 00789 00790 return 0; 00791 }
|
|
Definition at line 403 of file app_meetme.c. References ast_channel::_softhangup, ast_autoservice_start(), ast_autoservice_stop(), ast_mutex_lock(), ast_mutex_unlock(), careful_write(), enter, ENTER, ast_conference::fd, leave, and LEAVE. Referenced by conf_run(). 00404 { 00405 unsigned char *data; 00406 int len; 00407 int res = -1; 00408 00409 if (!chan->_softhangup) 00410 res = ast_autoservice_start(chan); 00411 00412 ast_mutex_lock(&conflock); 00413 00414 switch(sound) { 00415 case ENTER: 00416 data = enter; 00417 len = sizeof(enter); 00418 break; 00419 case LEAVE: 00420 data = leave; 00421 len = sizeof(leave); 00422 break; 00423 default: 00424 data = NULL; 00425 len = 0; 00426 } 00427 if (data) 00428 careful_write(conf->fd, data, len, 1); 00429 00430 ast_mutex_unlock(&conflock); 00431 00432 if (!res) 00433 ast_autoservice_stop(chan); 00434 }
|
|
Definition at line 793 of file app_meetme.c. References ADMINFLAG_KICKME, ADMINFLAG_MUTED, ast_conf_user::adminflags, app, ast_channel_setoption(), ast_config_AST_SPOOL_DIR, AST_DIGIT_ANY, ast_dsp_free(), ast_dsp_new(), ast_dsp_silence(), ast_filedelete(), ast_fileexists(), AST_FORMAT_SLINEAR, ast_frame_adjust_volume(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), AST_FRIENDLY_OFFSET, ast_goto_if_exists(), ast_indicate(), ast_log(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), AST_OPTION_TONE_VERIFY, ast_pthread_create, ast_read(), ast_record_review(), ast_say_number(), ast_set_read_format(), ast_set_write_format(), ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_verbose(), ast_waitfor_nandfds(), ast_waitstream(), ast_write(), ast_conference::attr, audio_buffers, calloc, careful_write(), ast_conference::chan, ast_conf_user::chan, conf_flush(), conf_free(), conf_play(), CONF_SIZE, CONFFLAG_ADMIN, CONFFLAG_AGI, CONFFLAG_ANNOUNCEUSERCOUNT, CONFFLAG_EXIT_CONTEXT, CONFFLAG_INTROUSER, CONFFLAG_MARKEDEXIT, CONFFLAG_MARKEDUSER, CONFFLAG_MOH, CONFFLAG_MONITOR, CONFFLAG_MONITORTALKER, CONFFLAG_POUNDEXIT, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFFLAG_STARMENU, CONFFLAG_TALKER, CONFFLAG_WAITMARKED, ast_conference::confno, ast_channel::context, dsp, ENTER, EVENT_FLAG_CALL, exitcontext, ast_channel::fds, ast_conference::firstuser, ast_frame::frametype, free, ast_channel::language, ast_conference::lastuser, LEAVE, ast_conference::locked, LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_channel::macrocontext, manager_event(), ast_conference::markedusers, MEETME_DELAYDETECTENDTALK, MEETME_DELAYDETECTTALK, MEETME_RECORD_ACTIVE, ast_channel::name, ast_conf_user::nextuser, option_debug, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), ast_conf_user::prevuser, ast_conference::recording, ast_conference::recordingfilename, ast_conference::recordingformat, recordthread(), ast_conference::recordthread, reset_volumes(), set_talk_volume(), ast_frame::subclass, tweak_listen_volume(), tweak_talk_volume(), ast_channel::type, ast_channel::uniqueid, user, ast_conf_user::user_no, ast_conf_user::userflags, ast_conference::users, VERBOSE_PREFIX_4, VOL_DOWN, VOL_UP, and ast_conference::zapconf. Referenced by conf_exec(). 00794 { 00795 struct ast_conf_user *user = calloc(1, sizeof(*user)); 00796 struct ast_conf_user *usr = NULL; 00797 int fd; 00798 struct zt_confinfo ztc, ztc_empty; 00799 struct ast_frame *f; 00800 struct ast_channel *c; 00801 struct ast_frame fr; 00802 int outfd; 00803 int ms; 00804 int nfds; 00805 int res; 00806 int flags; 00807 int retryzap; 00808 int origfd; 00809 int musiconhold = 0; 00810 int firstpass = 0; 00811 int lastmarked = 0; 00812 int currentmarked = 0; 00813 int ret = -1; 00814 int x; 00815 int menu_active = 0; 00816 int using_pseudo = 0; 00817 int duration=20; 00818 struct ast_dsp *dsp=NULL; 00819 struct ast_app *app; 00820 char *agifile; 00821 char *agifiledefault = "conf-background.agi"; 00822 char meetmesecs[30] = ""; 00823 char exitcontext[AST_MAX_CONTEXT] = ""; 00824 char recordingtmp[AST_MAX_EXTENSION] = ""; 00825 int dtmf; 00826 ZT_BUFFERINFO bi; 00827 char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; 00828 char *buf = __buf + AST_FRIENDLY_OFFSET; 00829 00830 if (!user) { 00831 ast_log(LOG_ERROR, "Out of memory\n"); 00832 return ret; 00833 } 00834 00835 if (confflags & CONFFLAG_RECORDCONF && conf->recording !=MEETME_RECORD_ACTIVE) { 00836 conf->recordingfilename = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFILE"); 00837 if (!conf->recordingfilename) { 00838 snprintf(recordingtmp, sizeof(recordingtmp), "meetme-conf-rec-%s-%s", conf->confno, chan->uniqueid); 00839 conf->recordingfilename = ast_strdupa(recordingtmp); 00840 } 00841 conf->recordingformat = pbx_builtin_getvar_helper(chan, "MEETME_RECORDINGFORMAT"); 00842 if (!conf->recordingformat) { 00843 snprintf(recordingtmp, sizeof(recordingtmp), "wav"); 00844 conf->recordingformat = ast_strdupa(recordingtmp); 00845 } 00846 pthread_attr_init(&conf->attr); 00847 pthread_attr_setdetachstate(&conf->attr, PTHREAD_CREATE_DETACHED); 00848 ast_verbose(VERBOSE_PREFIX_4 "Starting recording of MeetMe Conference %s into file %s.%s.\n", 00849 conf->confno, conf->recordingfilename, conf->recordingformat); 00850 ast_pthread_create(&conf->recordthread, &conf->attr, recordthread, conf); 00851 } 00852 00853 time(&user->jointime); 00854 00855 if (conf->locked && (!(confflags & CONFFLAG_ADMIN))) { 00856 /* Sorry, but this confernce is locked! */ 00857 if (!ast_streamfile(chan, "conf-locked", chan->language)) 00858 ast_waitstream(chan, ""); 00859 goto outrun; 00860 } 00861 00862 if (confflags & CONFFLAG_MARKEDUSER) 00863 conf->markedusers++; 00864 00865 ast_mutex_lock(&conflock); 00866 if (!conf->firstuser) { 00867 /* Fill the first new User struct */ 00868 user->user_no = 1; 00869 conf->firstuser = user; 00870 conf->lastuser = user; 00871 } else { 00872 /* Fill the new user struct */ 00873 user->user_no = conf->lastuser->user_no + 1; 00874 user->prevuser = conf->lastuser; 00875 if (conf->lastuser->nextuser) { 00876 ast_log(LOG_WARNING, "Error in User Management!\n"); 00877 ast_mutex_unlock(&conflock); 00878 goto outrun; 00879 } else { 00880 conf->lastuser->nextuser = user; 00881 conf->lastuser = user; 00882 } 00883 } 00884 00885 user->chan = chan; 00886 user->userflags = confflags; 00887 user->adminflags = 0; 00888 user->talking = -1; 00889 conf->users++; 00890 ast_mutex_unlock(&conflock); 00891 00892 if (confflags & CONFFLAG_EXIT_CONTEXT) { 00893 if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 00894 ast_copy_string(exitcontext, agifile, sizeof(exitcontext)); 00895 else if (!ast_strlen_zero(chan->macrocontext)) 00896 ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); 00897 else 00898 ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); 00899 } 00900 00901 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_INTROUSER)) { 00902 snprintf(user->namerecloc, sizeof(user->namerecloc), 00903 "%s/meetme/meetme-username-%s-%d", ast_config_AST_SPOOL_DIR, 00904 conf->confno, user->user_no); 00905 res = ast_record_review(chan, "vm-rec-name", user->namerecloc, 10, "sln", &duration, NULL); 00906 if (res == -1) 00907 goto outrun; 00908 } 00909 00910 if (!(confflags & CONFFLAG_QUIET)) { 00911 if (conf->users == 1 && !(confflags & CONFFLAG_WAITMARKED)) 00912 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 00913 ast_waitstream(chan, ""); 00914 if ((confflags & CONFFLAG_WAITMARKED) && conf->markedusers == 0) 00915 if (!ast_streamfile(chan, "conf-waitforleader", chan->language)) 00916 ast_waitstream(chan, ""); 00917 } 00918 00919 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_ANNOUNCEUSERCOUNT) && conf->users > 1) { 00920 int keepplaying = 1; 00921 00922 if (conf->users == 2) { 00923 if (!ast_streamfile(chan,"conf-onlyone",chan->language)) { 00924 res = ast_waitstream(chan, AST_DIGIT_ANY); 00925 if (res > 0) 00926 keepplaying=0; 00927 else if (res == -1) 00928 goto outrun; 00929 } 00930 } else { 00931 if (!ast_streamfile(chan, "conf-thereare", chan->language)) { 00932 res = ast_waitstream(chan, AST_DIGIT_ANY); 00933 if (res > 0) 00934 keepplaying=0; 00935 else if (res == -1) 00936 goto outrun; 00937 } 00938 if (keepplaying) { 00939 res = ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 00940 if (res > 0) 00941 keepplaying=0; 00942 else if (res == -1) 00943 goto outrun; 00944 } 00945 if (keepplaying && !ast_streamfile(chan, "conf-otherinparty", chan->language)) { 00946 res = ast_waitstream(chan, AST_DIGIT_ANY); 00947 if (res > 0) 00948 keepplaying=0; 00949 else if (res == -1) 00950 goto outrun; 00951 } 00952 } 00953 } 00954 00955 ast_indicate(chan, -1); 00956 00957 if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { 00958 ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); 00959 goto outrun; 00960 } 00961 00962 if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { 00963 ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); 00964 goto outrun; 00965 } 00966 00967 retryzap = strcasecmp(chan->type, "Zap"); 00968 user->zapchannel = !retryzap; 00969 00970 zapretry: 00971 origfd = chan->fds[0]; 00972 if (retryzap) { 00973 fd = open("/dev/zap/pseudo", O_RDWR); 00974 if (fd < 0) { 00975 ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); 00976 goto outrun; 00977 } 00978 using_pseudo = 1; 00979 /* Make non-blocking */ 00980 flags = fcntl(fd, F_GETFL); 00981 if (flags < 0) { 00982 ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); 00983 close(fd); 00984 goto outrun; 00985 } 00986 if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { 00987 ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); 00988 close(fd); 00989 goto outrun; 00990 } 00991 /* Setup buffering information */ 00992 memset(&bi, 0, sizeof(bi)); 00993 bi.bufsize = CONF_SIZE/2; 00994 bi.txbufpolicy = ZT_POLICY_IMMEDIATE; 00995 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE; 00996 bi.numbufs = audio_buffers; 00997 if (ioctl(fd, ZT_SET_BUFINFO, &bi)) { 00998 ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); 00999 close(fd); 01000 goto outrun; 01001 } 01002 x = 1; 01003 if (ioctl(fd, ZT_SETLINEAR, &x)) { 01004 ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); 01005 close(fd); 01006 goto outrun; 01007 } 01008 nfds = 1; 01009 } else { 01010 /* XXX Make sure we're not running on a pseudo channel XXX */ 01011 fd = chan->fds[0]; 01012 nfds = 0; 01013 } 01014 memset(&ztc, 0, sizeof(ztc)); 01015 memset(&ztc_empty, 0, sizeof(ztc_empty)); 01016 /* Check to see if we're in a conference... */ 01017 ztc.chan = 0; 01018 if (ioctl(fd, ZT_GETCONF, &ztc)) { 01019 ast_log(LOG_WARNING, "Error getting conference\n"); 01020 close(fd); 01021 goto outrun; 01022 } 01023 if (ztc.confmode) { 01024 /* Whoa, already in a conference... Retry... */ 01025 if (!retryzap) { 01026 ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n"); 01027 retryzap = 1; 01028 goto zapretry; 01029 } 01030 } 01031 memset(&ztc, 0, sizeof(ztc)); 01032 /* Add us to the conference */ 01033 ztc.chan = 0; 01034 ztc.confno = conf->zapconf; 01035 01036 ast_mutex_lock(&conflock); 01037 01038 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_INTROUSER) && conf->users > 1) { 01039 if (conf->chan && ast_fileexists(user->namerecloc, NULL, NULL)) { 01040 if (!ast_streamfile(conf->chan, user->namerecloc, chan->language)) 01041 ast_waitstream(conf->chan, ""); 01042 if (!ast_streamfile(conf->chan, "conf-hasjoin", chan->language)) 01043 ast_waitstream(conf->chan, ""); 01044 } 01045 } 01046 01047 if (confflags & CONFFLAG_MONITOR) 01048 ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER; 01049 else if (confflags & CONFFLAG_TALKER) 01050 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER; 01051 else 01052 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; 01053 01054 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01055 ast_log(LOG_WARNING, "Error setting conference\n"); 01056 close(fd); 01057 ast_mutex_unlock(&conflock); 01058 goto outrun; 01059 } 01060 ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf); 01061 01062 manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 01063 "Channel: %s\r\n" 01064 "Uniqueid: %s\r\n" 01065 "Meetme: %s\r\n" 01066 "Usernum: %d\r\n", 01067 chan->name, chan->uniqueid, conf->confno, user->user_no); 01068 01069 if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { 01070 firstpass = 1; 01071 if (!(confflags & CONFFLAG_QUIET)) 01072 if (!(confflags & CONFFLAG_WAITMARKED) || ((confflags & CONFFLAG_MARKEDUSER) && (conf->markedusers >= 1))) 01073 conf_play(chan, conf, ENTER); 01074 } 01075 01076 ast_mutex_unlock(&conflock); 01077 01078 conf_flush(fd, chan); 01079 01080 if (confflags & CONFFLAG_AGI) { 01081 /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) 01082 or use default filename of conf-background.agi */ 01083 01084 agifile = pbx_builtin_getvar_helper(chan, "MEETME_AGI_BACKGROUND"); 01085 if (!agifile) 01086 agifile = agifiledefault; 01087 01088 if (user->zapchannel) { 01089 /* Set CONFMUTE mode on Zap channel to mute DTMF tones */ 01090 x = 1; 01091 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01092 } 01093 /* Find a pointer to the agi app and execute the script */ 01094 app = pbx_findapp("agi"); 01095 if (app) { 01096 ret = pbx_exec(chan, app, agifile, 1); 01097 } else { 01098 ast_log(LOG_WARNING, "Could not find application (agi)\n"); 01099 ret = -2; 01100 } 01101 if (user->zapchannel) { 01102 /* Remove CONFMUTE mode on Zap channel */ 01103 x = 0; 01104 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01105 } 01106 } else { 01107 if (user->zapchannel && (confflags & CONFFLAG_STARMENU)) { 01108 /* Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */ 01109 x = 1; 01110 ast_channel_setoption(chan, AST_OPTION_TONE_VERIFY, &x, sizeof(char), 0); 01111 } 01112 if (confflags & CONFFLAG_MONITORTALKER && !(dsp = ast_dsp_new())) { 01113 ast_log(LOG_WARNING, "Unable to allocate DSP!\n"); 01114 res = -1; 01115 } 01116 for(;;) { 01117 int menu_was_active = 0; 01118 01119 outfd = -1; 01120 ms = -1; 01121 01122 /* if we have just exited from the menu, and the user had a channel-driver 01123 volume adjustment, restore it 01124 */ 01125 if (!menu_active && menu_was_active && user->listen.desired && !user->listen.actual) 01126 set_talk_volume(user, user->listen.desired); 01127 01128 menu_was_active = menu_active; 01129 01130 currentmarked = conf->markedusers; 01131 if (!(confflags & CONFFLAG_QUIET) && 01132 (confflags & CONFFLAG_MARKEDUSER) && 01133 (confflags & CONFFLAG_WAITMARKED) && 01134 lastmarked == 0) { 01135 if (currentmarked == 1 && conf->users > 1) { 01136 ast_say_number(chan, conf->users - 1, AST_DIGIT_ANY, chan->language, (char *) NULL); 01137 if (conf->users - 1 == 1) { 01138 if (!ast_streamfile(chan, "conf-userwilljoin", chan->language)) 01139 ast_waitstream(chan, ""); 01140 } else { 01141 if (!ast_streamfile(chan, "conf-userswilljoin", chan->language)) 01142 ast_waitstream(chan, ""); 01143 } 01144 } 01145 if (conf->users == 1 && ! (confflags & CONFFLAG_MARKEDUSER)) 01146 if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) 01147 ast_waitstream(chan, ""); 01148 } 01149 01150 c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); 01151 01152 /* Update the struct with the actual confflags */ 01153 user->userflags = confflags; 01154 01155 if (confflags & CONFFLAG_WAITMARKED) { 01156 if(currentmarked == 0) { 01157 if (lastmarked != 0) { 01158 if (!(confflags & CONFFLAG_QUIET)) 01159 if (!ast_streamfile(chan, "conf-leaderhasleft", chan->language)) 01160 ast_waitstream(chan, ""); 01161 if(confflags & CONFFLAG_MARKEDEXIT) 01162 break; 01163 else { 01164 ztc.confmode = ZT_CONF_CONF; 01165 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01166 ast_log(LOG_WARNING, "Error setting conference\n"); 01167 close(fd); 01168 goto outrun; 01169 } 01170 } 01171 } 01172 if (musiconhold == 0 && (confflags & CONFFLAG_MOH)) { 01173 ast_moh_start(chan, NULL); 01174 musiconhold = 1; 01175 } else { 01176 ztc.confmode = ZT_CONF_CONF; 01177 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01178 ast_log(LOG_WARNING, "Error setting conference\n"); 01179 close(fd); 01180 goto outrun; 01181 } 01182 } 01183 } else if(currentmarked >= 1 && lastmarked == 0) { 01184 if (confflags & CONFFLAG_MONITOR) 01185 ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER; 01186 else if (confflags & CONFFLAG_TALKER) 01187 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER; 01188 else 01189 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; 01190 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01191 ast_log(LOG_WARNING, "Error setting conference\n"); 01192 close(fd); 01193 goto outrun; 01194 } 01195 if (musiconhold && (confflags & CONFFLAG_MOH)) { 01196 ast_moh_stop(chan); 01197 musiconhold = 0; 01198 } 01199 if ( !(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MARKEDUSER)) { 01200 if (!ast_streamfile(chan, "conf-placeintoconf", chan->language)) 01201 ast_waitstream(chan, ""); 01202 conf_play(chan, conf, ENTER); 01203 } 01204 } 01205 } 01206 01207 /* trying to add moh for single person conf */ 01208 if ((confflags & CONFFLAG_MOH) && !(confflags & CONFFLAG_WAITMARKED)) { 01209 if (conf->users == 1) { 01210 if (musiconhold == 0) { 01211 ast_moh_start(chan, NULL); 01212 musiconhold = 1; 01213 } 01214 } else { 01215 if (musiconhold) { 01216 ast_moh_stop(chan); 01217 musiconhold = 0; 01218 } 01219 } 01220 } 01221 01222 /* Leave if the last marked user left */ 01223 if (currentmarked == 0 && lastmarked != 0 && (confflags & CONFFLAG_MARKEDEXIT)) { 01224 ret = -1; 01225 break; 01226 } 01227 01228 /* Check if the admin changed my modes */ 01229 if (user->adminflags) { 01230 /* Set the new modes */ 01231 if ((user->adminflags & ADMINFLAG_MUTED) && (ztc.confmode & ZT_CONF_TALKER)) { 01232 ztc.confmode ^= ZT_CONF_TALKER; 01233 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01234 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01235 ret = -1; 01236 break; 01237 } 01238 } 01239 if (!(user->adminflags & ADMINFLAG_MUTED) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) { 01240 ztc.confmode |= ZT_CONF_TALKER; 01241 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01242 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01243 ret = -1; 01244 break; 01245 } 01246 } 01247 if (user->adminflags & ADMINFLAG_KICKME) { 01248 /* You have been kicked. */ 01249 if (!ast_streamfile(chan, "conf-kicked", chan->language)) 01250 ast_waitstream(chan, ""); 01251 ret = 0; 01252 break; 01253 } 01254 } else if (!(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) { 01255 ztc.confmode |= ZT_CONF_TALKER; 01256 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01257 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01258 ret = -1; 01259 break; 01260 } 01261 } 01262 01263 if (c) { 01264 if (c->fds[0] != origfd) { 01265 if (using_pseudo) { 01266 /* Kill old pseudo */ 01267 close(fd); 01268 using_pseudo = 0; 01269 } 01270 ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n"); 01271 retryzap = strcasecmp(c->type, "Zap"); 01272 user->zapchannel = !retryzap; 01273 goto zapretry; 01274 } 01275 f = ast_read(c); 01276 if (!f) 01277 break; 01278 if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) { 01279 if (user->talk.actual) 01280 ast_frame_adjust_volume(f, user->talk.actual); 01281 01282 if (confflags & CONFFLAG_MONITORTALKER) { 01283 int totalsilence; 01284 01285 if (user->talking == -1) 01286 user->talking = 0; 01287 01288 res = ast_dsp_silence(dsp, f, &totalsilence); 01289 if (!user->talking && totalsilence < MEETME_DELAYDETECTTALK) { 01290 user->talking = 1; 01291 manager_event(EVENT_FLAG_CALL, "MeetmeTalking", 01292 "Channel: %s\r\n" 01293 "Uniqueid: %s\r\n" 01294 "Meetme: %s\r\n" 01295 "Usernum: %d\r\n", 01296 chan->name, chan->uniqueid, conf->confno, user->user_no); 01297 } 01298 if (user->talking && totalsilence > MEETME_DELAYDETECTENDTALK) { 01299 user->talking = 0; 01300 manager_event(EVENT_FLAG_CALL, "MeetmeStopTalking", 01301 "Channel: %s\r\n" 01302 "Uniqueid: %s\r\n" 01303 "Meetme: %s\r\n" 01304 "Usernum: %d\r\n", 01305 chan->name, chan->uniqueid, conf->confno, user->user_no); 01306 } 01307 } 01308 if (using_pseudo) { 01309 /* Absolutely do _not_ use careful_write here... 01310 it is important that we read data from the channel 01311 as fast as it arrives, and feed it into the conference. 01312 The buffering in the pseudo channel will take care of any 01313 timing differences, unless they are so drastic as to lose 01314 audio frames (in which case carefully writing would only 01315 have delayed the audio even further). 01316 */ 01317 /* As it turns out, we do want to use careful write. We just 01318 don't want to block, but we do want to at least *try* 01319 to write out all the samples. 01320 */ 01321 careful_write(fd, f->data, f->datalen, 0); 01322 } 01323 } else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) { 01324 char tmp[2]; 01325 01326 tmp[0] = f->subclass; 01327 tmp[1] = '\0'; 01328 if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) { 01329 ret = 0; 01330 ast_frfree(f); 01331 break; 01332 } else if (option_debug > 1) 01333 ast_log(LOG_DEBUG, "Exit by single digit did not work in meetme. Extension %s does not exist in context %s\n", tmp, exitcontext); 01334 } else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) { 01335 ret = 0; 01336 ast_frfree(f); 01337 break; 01338 } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) { 01339 if (ioctl(fd, ZT_SETCONF, &ztc_empty)) { 01340 ast_log(LOG_WARNING, "Error setting conference\n"); 01341 close(fd); 01342 ast_frfree(f); 01343 goto outrun; 01344 } 01345 01346 /* if we are entering the menu, and the user has a channel-driver 01347 volume adjustment, clear it 01348 */ 01349 if (!menu_active && user->talk.desired && !user->talk.actual) 01350 set_talk_volume(user, 0); 01351 01352 if (musiconhold) { 01353 ast_moh_stop(chan); 01354 } 01355 if ((confflags & CONFFLAG_ADMIN)) { 01356 /* Admin menu */ 01357 if (!menu_active) { 01358 menu_active = 1; 01359 /* Record this sound! */ 01360 if (!ast_streamfile(chan, "conf-adminmenu", chan->language)) { 01361 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 01362 ast_stopstream(chan); 01363 } else 01364 dtmf = 0; 01365 } else 01366 dtmf = f->subclass; 01367 if (dtmf) { 01368 switch(dtmf) { 01369 case '1': /* Un/Mute */ 01370 menu_active = 0; 01371 if (ztc.confmode & ZT_CONF_TALKER) { 01372 ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER; 01373 confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER; 01374 } else { 01375 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; 01376 confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER; 01377 } 01378 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01379 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01380 ret = -1; 01381 break; 01382 } 01383 if (ztc.confmode & ZT_CONF_TALKER) { 01384 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 01385 ast_waitstream(chan, ""); 01386 } else { 01387 if (!ast_streamfile(chan, "conf-muted", chan->language)) 01388 ast_waitstream(chan, ""); 01389 } 01390 break; 01391 case '2': /* Un/Lock the Conference */ 01392 menu_active = 0; 01393 if (conf->locked) { 01394 conf->locked = 0; 01395 if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) 01396 ast_waitstream(chan, ""); 01397 } else { 01398 conf->locked = 1; 01399 if (!ast_streamfile(chan, "conf-lockednow", chan->language)) 01400 ast_waitstream(chan, ""); 01401 } 01402 break; 01403 case '3': /* Eject last user */ 01404 menu_active = 0; 01405 usr = conf->lastuser; 01406 if ((usr->chan->name == chan->name)||(usr->userflags & CONFFLAG_ADMIN)) { 01407 if(!ast_streamfile(chan, "conf-errormenu", chan->language)) 01408 ast_waitstream(chan, ""); 01409 } else 01410 usr->adminflags |= ADMINFLAG_KICKME; 01411 ast_stopstream(chan); 01412 break; 01413 case '4': 01414 tweak_listen_volume(user, VOL_DOWN); 01415 break; 01416 case '6': 01417 tweak_listen_volume(user, VOL_UP); 01418 break; 01419 case '7': 01420 tweak_talk_volume(user, VOL_DOWN); 01421 break; 01422 case '8': 01423 menu_active = 0; 01424 break; 01425 case '9': 01426 tweak_talk_volume(user, VOL_UP); 01427 break; 01428 default: 01429 menu_active = 0; 01430 /* Play an error message! */ 01431 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 01432 ast_waitstream(chan, ""); 01433 break; 01434 } 01435 } 01436 } else { 01437 /* User menu */ 01438 if (!menu_active) { 01439 menu_active = 1; 01440 if (!ast_streamfile(chan, "conf-usermenu", chan->language)) { 01441 dtmf = ast_waitstream(chan, AST_DIGIT_ANY); 01442 ast_stopstream(chan); 01443 } else 01444 dtmf = 0; 01445 } else 01446 dtmf = f->subclass; 01447 if (dtmf) { 01448 switch(dtmf) { 01449 case '1': /* Un/Mute */ 01450 menu_active = 0; 01451 if (ztc.confmode & ZT_CONF_TALKER) { 01452 ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER; 01453 confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER; 01454 } else if (!(user->adminflags & ADMINFLAG_MUTED)) { 01455 ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; 01456 confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER; 01457 } 01458 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01459 ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); 01460 ret = -1; 01461 break; 01462 } 01463 if (ztc.confmode & ZT_CONF_TALKER) { 01464 if (!ast_streamfile(chan, "conf-unmuted", chan->language)) 01465 ast_waitstream(chan, ""); 01466 } else { 01467 if (!ast_streamfile(chan, "conf-muted", chan->language)) 01468 ast_waitstream(chan, ""); 01469 } 01470 break; 01471 case '4': 01472 tweak_listen_volume(user, VOL_DOWN); 01473 break; 01474 case '6': 01475 tweak_listen_volume(user, VOL_UP); 01476 break; 01477 case '7': 01478 tweak_talk_volume(user, VOL_DOWN); 01479 break; 01480 case '8': 01481 menu_active = 0; 01482 break; 01483 case '9': 01484 tweak_talk_volume(user, VOL_UP); 01485 break; 01486 default: 01487 menu_active = 0; 01488 if (!ast_streamfile(chan, "conf-errormenu", chan->language)) 01489 ast_waitstream(chan, ""); 01490 break; 01491 } 01492 } 01493 } 01494 if (musiconhold) 01495 ast_moh_start(chan, NULL); 01496 01497 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01498 ast_log(LOG_WARNING, "Error setting conference\n"); 01499 close(fd); 01500 ast_frfree(f); 01501 goto outrun; 01502 } 01503 01504 conf_flush(fd, chan); 01505 } else if (option_debug) { 01506 ast_log(LOG_DEBUG, 01507 "Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n", 01508 chan->name, f->frametype, f->subclass); 01509 } 01510 ast_frfree(f); 01511 } else if (outfd > -1) { 01512 res = read(outfd, buf, CONF_SIZE); 01513 if (res > 0) { 01514 memset(&fr, 0, sizeof(fr)); 01515 fr.frametype = AST_FRAME_VOICE; 01516 fr.subclass = AST_FORMAT_SLINEAR; 01517 fr.datalen = res; 01518 fr.samples = res/2; 01519 fr.data = buf; 01520 fr.offset = AST_FRIENDLY_OFFSET; 01521 if (user->listen.actual) 01522 ast_frame_adjust_volume(&fr, user->listen.actual); 01523 if (ast_write(chan, &fr) < 0) { 01524 ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno)); 01525 } 01526 } else 01527 ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); 01528 } 01529 lastmarked = currentmarked; 01530 } 01531 } 01532 01533 if (musiconhold) 01534 ast_moh_stop(chan); 01535 01536 if (using_pseudo) 01537 close(fd); 01538 else { 01539 /* Take out of conference */ 01540 ztc.chan = 0; 01541 ztc.confno = 0; 01542 ztc.confmode = 0; 01543 if (ioctl(fd, ZT_SETCONF, &ztc)) { 01544 ast_log(LOG_WARNING, "Error setting conference\n"); 01545 } 01546 } 01547 01548 reset_volumes(user); 01549 01550 ast_mutex_lock(&conflock); 01551 if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) 01552 conf_play(chan, conf, LEAVE); 01553 01554 if (!(confflags & CONFFLAG_QUIET) && (confflags & CONFFLAG_INTROUSER)) { 01555 if (ast_fileexists(user->namerecloc, NULL, NULL)) { 01556 if ((conf->chan) && (conf->users > 1)) { 01557 if (!ast_streamfile(conf->chan, user->namerecloc, chan->language)) 01558 ast_waitstream(conf->chan, ""); 01559 if (!ast_streamfile(conf->chan, "conf-hasleft", chan->language)) 01560 ast_waitstream(conf->chan, ""); 01561 } 01562 ast_filedelete(user->namerecloc, NULL); 01563 } 01564 } 01565 ast_mutex_unlock(&conflock); 01566 01567 outrun: 01568 ast_mutex_lock(&conflock); 01569 01570 if (confflags & CONFFLAG_MONITORTALKER && dsp) 01571 ast_dsp_free(dsp); 01572 01573 if (user->user_no) { /* Only cleanup users who really joined! */ 01574 manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 01575 "Channel: %s\r\n" 01576 "Uniqueid: %s\r\n" 01577 "Meetme: %s\r\n" 01578 "Usernum: %d\r\n", 01579 chan->name, chan->uniqueid, conf->confno, user->user_no); 01580 conf->users--; 01581 if (confflags & CONFFLAG_MARKEDUSER) 01582 conf->markedusers--; 01583 if (!conf->users) { 01584 /* No more users -- close this one out */ 01585 conf_free(conf); 01586 } else { 01587 /* Remove the user struct */ 01588 if (user == conf->firstuser) { 01589 if (user->nextuser) { 01590 /* There is another entry */ 01591 user->nextuser->prevuser = NULL; 01592 } else { 01593 /* We are the only entry */ 01594 conf->lastuser = NULL; 01595 } 01596 /* In either case */ 01597 conf->firstuser = user->nextuser; 01598 } else if (user == conf->lastuser){ 01599 if (user->prevuser) 01600 user->prevuser->nextuser = NULL; 01601 else 01602 ast_log(LOG_ERROR, "Bad bad bad! We're the last, not the first, but nobody before us??\n"); 01603 conf->lastuser = user->prevuser; 01604 } else { 01605 if (user->nextuser) 01606 user->nextuser->prevuser = user->prevuser; 01607 else 01608 ast_log(LOG_ERROR, "Bad! Bad! Bad! user->nextuser is NULL but we're not the end!\n"); 01609 if (user->prevuser) 01610 user->prevuser->nextuser = user->nextuser; 01611 else 01612 ast_log(LOG_ERROR, "Bad! Bad! Bad! user->prevuser is NULL but we're not the beginning!\n"); 01613 } 01614 } 01615 /* Return the number of seconds the user was in the conf */ 01616 snprintf(meetmesecs, sizeof(meetmesecs), "%d", (int) (time(NULL) - user->jointime)); 01617 pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); 01618 } 01619 free(user); 01620 ast_mutex_unlock(&conflock); 01621 01622 return ret; 01623 }
|
|
Definition at line 503 of file app_meetme.c. References ast_cli(), and RESULT_SUCCESS. 00504 { 00505 ast_cli(fd, "Deprecated! Please use 'meetme' instead.\n"); 00506 00507 return RESULT_SUCCESS; 00508 }
|
|
Definition at line 1720 of file app_meetme.c. References ast_channel::_state, ast_answer(), ast_log(), ast_say_number(), AST_STATE_UP, ast_strdupa, ast_strlen_zero(), find_conf(), LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_ERROR, LOG_WARNING, pbx_builtin_setvar_helper(), strsep(), and ast_conference::users. Referenced by load_module(). 01721 { 01722 struct localuser *u; 01723 int res = 0; 01724 struct ast_conference *conf; 01725 int count; 01726 char *confnum, *localdata; 01727 char val[80] = "0"; 01728 01729 if (ast_strlen_zero(data)) { 01730 ast_log(LOG_WARNING, "MeetMeCount requires an argument (conference number)\n"); 01731 return -1; 01732 } 01733 01734 LOCAL_USER_ADD(u); 01735 01736 localdata = ast_strdupa(data); 01737 if (!localdata) { 01738 ast_log(LOG_ERROR, "Out of memory!\n"); 01739 LOCAL_USER_REMOVE(u); 01740 return -1; 01741 } 01742 01743 confnum = strsep(&localdata,"|"); 01744 conf = find_conf(chan, confnum, 0, 0, NULL, NULL); 01745 if (conf) 01746 count = conf->users; 01747 else 01748 count = 0; 01749 01750 if (!ast_strlen_zero(localdata)){ 01751 /* have var so load it and exit */ 01752 snprintf(val, sizeof(val), "%d",count); 01753 pbx_builtin_setvar_helper(chan, localdata, val); 01754 } else { 01755 if (chan->_state != AST_STATE_UP) 01756 ast_answer(chan); 01757 res = ast_say_number(chan, count, "", chan->language, (char *) NULL); /* Needs gender */ 01758 } 01759 LOCAL_USER_REMOVE(u); 01760 01761 return res; 01762 }
|
|
Provides a description of the module.
Definition at line 2261 of file app_meetme.c. References tdesc. 02262 { 02263 return (char *) tdesc; 02264 }
|
|
Definition at line 1625 of file app_meetme.c. References ast_app_getdata(), ast_clear_flag, ast_config_destroy(), ast_config_load(), ast_log(), AST_MAX_EXTENSION, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_test_flag, ast_variable_browse(), build_conf(), cfg, ast_conference::chan, CONFFLAG_INTROUSER, CONFFLAG_QUIET, CONFFLAG_RECORDCONF, CONFIG_FILE_NAME, ast_conference::confno, confs, LOG_DEBUG, LOG_WARNING, ast_variable::name, ast_variable::next, ast_conference::next, ast_conference::pin, ast_conference::pinadmin, strsep(), ast_variable::value, and var. Referenced by conf_exec(), and count_exec(). 01627 { 01628 struct ast_config *cfg; 01629 struct ast_variable *var; 01630 struct ast_conference *cnf; 01631 01632 /* Check first in the conference list */ 01633 ast_mutex_lock(&conflock); 01634 for (cnf = confs; cnf; cnf = cnf->next) { 01635 if (!strcmp(confno, cnf->confno)) 01636 break; 01637 } 01638 ast_mutex_unlock(&conflock); 01639 01640 if (!cnf) { 01641 if (dynamic) { 01642 /* No need to parse meetme.conf */ 01643 ast_log(LOG_DEBUG, "Building dynamic conference '%s'\n", confno); 01644 if (dynamic_pin) { 01645 if (dynamic_pin[0] == 'q') { 01646 /* Query the user to enter a PIN */ 01647 if (ast_app_getdata(chan, "conf-getpin", dynamic_pin, AST_MAX_EXTENSION - 1, 0) < 0) 01648 return NULL; 01649 } 01650 cnf = build_conf(confno, dynamic_pin, "", make, dynamic); 01651 } else { 01652 cnf = build_conf(confno, "", "", make, dynamic); 01653 } 01654 } else { 01655 /* Check the config */ 01656 cfg = ast_config_load(CONFIG_FILE_NAME); 01657 if (!cfg) { 01658 ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME); 01659 return NULL; 01660 } 01661 var = ast_variable_browse(cfg, "rooms"); 01662 while (var) { 01663 if (!strcasecmp(var->name, "conf")) { 01664 /* Separate the PIN */ 01665 char *pin, *pinadmin, *conf; 01666 01667 if ((pinadmin = ast_strdupa(var->value))) { 01668 conf = strsep(&pinadmin, "|,"); 01669 pin = strsep(&pinadmin, "|,"); 01670 if (!strcasecmp(conf, confno)) { 01671 /* Bingo it's a valid conference */ 01672 if (pin) 01673 if (pinadmin) 01674 cnf = build_conf(confno, pin, pinadmin, make, dynamic); 01675 else 01676 cnf = build_conf(confno, pin, "", make, dynamic); 01677 else 01678 if (pinadmin) 01679 cnf = build_conf(confno, "", pinadmin, make, dynamic); 01680 else 01681 cnf = build_conf(confno, "", "", make, dynamic); 01682 break; 01683 } 01684 } 01685 } 01686 var = var->next; 01687 } 01688 if (!var) { 01689 ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno); 01690 } 01691 ast_config_destroy(cfg); 01692 } 01693 } else if (dynamic_pin) { 01694 /* Correct for the user selecting 'D' instead of 'd' to have 01695 someone join into a conference that has already been created 01696 with a pin. */ 01697 if (dynamic_pin[0] == 'q') 01698 dynamic_pin[0] = '\0'; 01699 } 01700 01701 if (cnf) { 01702 if (confflags && !cnf->chan && 01703 !ast_test_flag(confflags, CONFFLAG_QUIET) && 01704 ast_test_flag(confflags, CONFFLAG_INTROUSER)) { 01705 ast_log(LOG_WARNING, "No Zap channel available for conference, user introduction disabled (is chan_zap loaded?)\n"); 01706 ast_clear_flag(confflags, CONFFLAG_INTROUSER); 01707 } 01708 01709 if (confflags && !cnf->chan && 01710 ast_test_flag(confflags, CONFFLAG_RECORDCONF)) { 01711 ast_log(LOG_WARNING, "No Zap channel available for conference, conference recording disabled (is chan_zap loaded?)\n"); 01712 ast_clear_flag(confflags, CONFFLAG_RECORDCONF); 01713 } 01714 } 01715 01716 return cnf; 01717 }
|
|
Definition at line 2017 of file app_meetme.c. References ast_conference::firstuser, ast_conf_user::nextuser, user, and ast_conf_user::user_no. 02018 { 02019 struct ast_conf_user *user = NULL; 02020 int cid; 02021 02022 if (!conf || !callerident) { 02023 return NULL; 02024 } 02025 02026 sscanf(callerident, "%i", &cid); 02027 02028 user = conf->firstuser; 02029 while (user) { 02030 if (user->user_no == cid) 02031 break; 02032 user = user->nextuser; 02033 } 02034 02035 return user; 02036 }
|
|
Definition at line 255 of file app_meetme.c. Referenced by conf_cmd(). 00256 { 00257 if (x > 0) 00258 return "(talking)"; 00259 else if (x < 0) 00260 return "(unmonitored)"; 00261 else 00262 return "(not talking)"; 00263 }
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 2275 of file app_meetme.c. References ASTERISK_GPL_KEY. 02276 { 02277 return ASTERISK_GPL_KEY; 02278 }
|
|
Definition at line 2198 of file app_meetme.c. References ast_config_destroy(), ast_config_load(), ast_log(), ast_variable_retrieve(), audio_buffers, cfg, CONFIG_FILE_NAME, DEFAULT_AUDIO_BUFFERS, LOG_NOTICE, and LOG_WARNING. 02199 { 02200 struct ast_config *cfg; 02201 char *val; 02202 02203 audio_buffers = DEFAULT_AUDIO_BUFFERS; 02204 02205 if (!(cfg = ast_config_load(CONFIG_FILE_NAME))) 02206 return; 02207 02208 if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) { 02209 if ((sscanf(val, "%d", &audio_buffers) != 1)) { 02210 ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val); 02211 audio_buffers = DEFAULT_AUDIO_BUFFERS; 02212 } else if ((audio_buffers < ZT_DEFAULT_NUM_BUFS) || (audio_buffers > ZT_MAX_NUM_BUFS)) { 02213 ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n", 02214 ZT_DEFAULT_NUM_BUFS, ZT_MAX_NUM_BUFS); 02215 audio_buffers = DEFAULT_AUDIO_BUFFERS; 02216 } 02217 if (audio_buffers != DEFAULT_AUDIO_BUFFERS) 02218 ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); 02219 } 02220 02221 ast_config_destroy(cfg); 02222 }
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 2239 of file app_meetme.c. References admin_exec(), app, app2, app3, ast_cli_register(), ast_register_application(), conf_exec(), count_exec(), descrip, descrip2, descrip3, load_config(), synopsis, synopsis2, and synopsis3. 02240 { 02241 int res; 02242 02243 load_config(); 02244 02245 res = ast_cli_register(&cli_show_confs); 02246 res |= ast_cli_register(&cli_conf); 02247 res |= ast_register_application(app3, admin_exec, synopsis3, descrip3); 02248 res |= ast_register_application(app2, count_exec, synopsis2, descrip2); 02249 res |= ast_register_application(app, conf_exec, synopsis, descrip); 02250 02251 return res; 02252 }
|
|
Definition at line 2155 of file app_meetme.c. References ast_closestream(), AST_FRAME_VOICE, ast_frfree(), ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_stopstream(), ast_waitfor(), ast_writefile(), ast_writestream(), ast_conference::chan, ast_frame::frametype, MEETME_RECORD_ACTIVE, MEETME_RECORD_OFF, MEETME_RECORD_TERMINATE, ast_conference::recording, ast_conference::recordingfilename, ast_conference::recordingformat, and s. Referenced by conf_run(). 02156 { 02157 struct ast_conference *cnf = args; 02158 struct ast_frame *f=NULL; 02159 int flags; 02160 struct ast_filestream *s; 02161 int res=0; 02162 02163 if (!cnf || !cnf->chan) { 02164 pthread_exit(0); 02165 } 02166 ast_stopstream(cnf->chan); 02167 flags = O_CREAT|O_TRUNC|O_WRONLY; 02168 s = ast_writefile(cnf->recordingfilename, cnf->recordingformat, NULL, flags, 0, 0644); 02169 02170 if (s) { 02171 cnf->recording = MEETME_RECORD_ACTIVE; 02172 while (ast_waitfor(cnf->chan, -1) > -1) { 02173 f = ast_read(cnf->chan); 02174 if (!f) { 02175 res = -1; 02176 break; 02177 } 02178 if (f->frametype == AST_FRAME_VOICE) { 02179 res = ast_writestream(s, f); 02180 if (res) { 02181 ast_frfree(f); 02182 break; 02183 } 02184 } 02185 ast_frfree(f); 02186 if (cnf->recording == MEETME_RECORD_TERMINATE) { 02187 ast_mutex_lock(&conflock); 02188 ast_mutex_unlock(&conflock); 02189 break; 02190 } 02191 } 02192 cnf->recording = MEETME_RECORD_OFF; 02193 ast_closestream(s); 02194 } 02195 pthread_exit(0); 02196 }
|
|
Reload stuff. This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.
Definition at line 2254 of file app_meetme.c. References load_config(). 02255 { 02256 load_config(); 02257 02258 return 0; 02259 }
|
|
Definition at line 395 of file app_meetme.c. References ast_channel_setoption(), AST_OPTION_RXGAIN, AST_OPTION_TXGAIN, and ast_conf_user::chan. Referenced by conf_run(). 00396 { 00397 signed char zero_volume = 0; 00398 00399 ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); 00400 ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &zero_volume, sizeof(zero_volume), 0); 00401 }
|
|
Definition at line 324 of file app_meetme.c. References ast_channel_setoption(), AST_OPTION_TXGAIN, and ast_conf_user::chan. Referenced by tweak_listen_volume(). 00325 { 00326 signed char gain_adjust; 00327 00328 /* attempt to make the adjustment in the channel driver; 00329 if successful, don't adjust in the frame reading routine 00330 */ 00331 gain_adjust = gain_map[volume + 5]; 00332 00333 return ast_channel_setoption(user->chan, AST_OPTION_TXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00334 }
|
|
Definition at line 312 of file app_meetme.c. References ast_channel_setoption(), AST_OPTION_RXGAIN, and ast_conf_user::chan. Referenced by conf_run(), and tweak_talk_volume(). 00313 { 00314 signed char gain_adjust; 00315 00316 /* attempt to make the adjustment in the channel driver; 00317 if successful, don't adjust in the frame reading routine 00318 */ 00319 gain_adjust = gain_map[volume + 5]; 00320 00321 return ast_channel_setoption(user->chan, AST_OPTION_RXGAIN, &gain_adjust, sizeof(gain_adjust), 0); 00322 }
|
|
Definition at line 383 of file app_meetme.c. References volume::actual, volume::desired, ast_conf_user::listen, set_listen_volume(), and tweak_volume(). Referenced by conf_run(). 00384 { 00385 tweak_volume(&user->listen, action); 00386 /* attempt to make the adjustment in the channel driver; 00387 if successful, don't adjust in the frame reading routine 00388 */ 00389 if (!set_listen_volume(user, user->listen.desired)) 00390 user->listen.actual = 0; 00391 else 00392 user->listen.actual = user->listen.desired; 00393 }
|
|
Definition at line 371 of file app_meetme.c. References set_talk_volume(), and tweak_volume(). Referenced by conf_run(). 00372 { 00373 tweak_volume(&user->talk, action); 00374 /* attempt to make the adjustment in the channel driver; 00375 if successful, don't adjust in the frame reading routine 00376 */ 00377 if (!set_talk_volume(user, user->talk.desired)) 00378 user->talk.actual = 0; 00379 else 00380 user->talk.actual = user->talk.desired; 00381 }
|
|
Definition at line 336 of file app_meetme.c. References volume::desired, VOL_DOWN, and VOL_UP. Referenced by tweak_listen_volume(), and tweak_talk_volume(). 00337 { 00338 switch (action) { 00339 case VOL_UP: 00340 switch (vol->desired) { 00341 case 5: 00342 break; 00343 case 0: 00344 vol->desired = 2; 00345 break; 00346 case -2: 00347 vol->desired = 0; 00348 break; 00349 default: 00350 vol->desired++; 00351 break; 00352 } 00353 break; 00354 case VOL_DOWN: 00355 switch (vol->desired) { 00356 case -5: 00357 break; 00358 case 2: 00359 vol->desired = 0; 00360 break; 00361 case 0: 00362 vol->desired = -2; 00363 break; 00364 default: 00365 vol->desired--; 00366 break; 00367 } 00368 } 00369 }
|
|
Cleanup all module structures, sockets, etc. This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 2224 of file app_meetme.c. References app, app2, app3, ast_cli_unregister(), ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS. 02225 { 02226 int res; 02227 02228 res = ast_cli_unregister(&cli_show_confs); 02229 res |= ast_cli_unregister(&cli_conf); 02230 res |= ast_unregister_application(app3); 02231 res |= ast_unregister_application(app2); 02232 res |= ast_unregister_application(app); 02233 02234 STANDARD_HANGUP_LOCALUSERS; 02235 02236 return res; 02237 }
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 2266 of file app_meetme.c. References STANDARD_USECOUNT. 02267 { 02268 int res; 02269 02270 STANDARD_USECOUNT(res); 02271 02272 return res; 02273 }
|
|
Definition at line 60 of file app_meetme.c. |
|
Definition at line 61 of file app_meetme.c. |
|
Definition at line 62 of file app_meetme.c. |
|
Definition at line 174 of file app_meetme.c. Referenced by conf_run(), and load_config(). |
|
Initial value: { {"meetme", NULL, NULL }, conf_cmd, "Execute a command on a conference or conferee", conf_usage, complete_confcmd} Definition at line 718 of file app_meetme.c. |
|
Initial value: { { "show", "conferences", NULL }, confs_show, "Show status of conferences", show_confs_usage, NULL } Definition at line 513 of file app_meetme.c. |
|
Initial value: "Usage: meetme (un)lock|(un)mute|kick|list <confno> <usernumber>\n" " Executes a command for the conference or on a conferee\n" Definition at line 714 of file app_meetme.c. |
|
Referenced by admin_exec(), build_conf(), complete_confcmd(), conf_cmd(), conf_exec(), conf_free(), and find_conf(). |
|
Definition at line 68 of file app_meetme.c. |
|
Definition at line 105 of file app_meetme.c. |
|
Definition at line 112 of file app_meetme.c. |
|
Definition at line 298 of file app_meetme.c. |
|
Definition at line 129 of file app_meetme.c. |
|
Initial value:
"Deprecated! Please use 'meetme' instead.\n"
Definition at line 510 of file app_meetme.c. |
|
Definition at line 127 of file app_meetme.c. |
|
Definition at line 64 of file app_meetme.c. |
|
Definition at line 65 of file app_meetme.c. |
|
Definition at line 66 of file app_meetme.c. |
|
Definition at line 58 of file app_meetme.c. |