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