Sat Sep 16 05:47:49 2006

Asterisk developer's documentation


app_meetme.c File Reference

Meet me conference bridge. More...

#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"

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_conferencebuild_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_conferencefind_conf (struct ast_channel *chan, char *confno, int make, int dynamic, char *dynamic_pin, struct ast_flags *confflags)
static struct ast_conf_userfind_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_conferenceconfs
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"


Detailed Description

Meet me conference bridge.

Definition in file app_meetme.c.


Define Documentation

#define ADMINFLAG_KICKME   (1 << 2)

Definition at line 182 of file app_meetme.c.

Referenced by admin_exec(), and conf_run().

#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

Definition at line 207 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_ADMIN   (1 << 1)

Definition at line 209 of file app_meetme.c.

Referenced by conf_cmd(), and conf_run().

#define CONFFLAG_AGI   (1 << 8)

Definition at line 216 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_ALWAYSPROMPT   (1 << 21)

Definition at line 229 of file app_meetme.c.

Referenced by conf_exec().

#define CONFFLAG_ANNOUNCEUSERCOUNT   (1 << 7)

Definition at line 215 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_DYNAMIC   (1 << 17)

Definition at line 225 of file app_meetme.c.

Referenced by conf_exec().

#define CONFFLAG_DYNAMICPIN   (1 << 18)

Definition at line 226 of file app_meetme.c.

Referenced by conf_exec().

#define CONFFLAG_EMPTY   (1 << 19)

Definition at line 227 of file app_meetme.c.

Referenced by conf_exec().

#define CONFFLAG_EMPTYNOPIN   (1 << 20)

Definition at line 228 of file app_meetme.c.

Referenced by conf_exec().

#define CONFFLAG_EXIT_CONTEXT   (1 << 12)

Definition at line 220 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_INTROUSER   (1 << 14)

Definition at line 222 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_MARKEDEXIT   (1 << 10)

Definition at line 218 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_MARKEDUSER   (1 << 13)

Definition at line 221 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_MOH   (1 << 9)

Definition at line 217 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_MONITOR   (1 << 2)

Definition at line 210 of file app_meetme.c.

Referenced by conf_cmd(), and conf_run().

#define CONFFLAG_MONITORTALKER   (1 << 16)

Definition at line 224 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_POUNDEXIT   (1 << 3)

Definition at line 211 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_QUIET   (1 << 6)

Definition at line 214 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_RECORDCONF   (1<< 15)

Definition at line 223 of file app_meetme.c.

Referenced by conf_run(), and find_conf().

#define CONFFLAG_STARMENU   (1 << 4)

Definition at line 212 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_TALKER   (1 << 5)

Definition at line 213 of file app_meetme.c.

Referenced by conf_run().

#define CONFFLAG_WAITMARKED   (1 << 11)

Definition at line 219 of file app_meetme.c.

Referenced by conf_run().

#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

Definition at line 179 of file app_meetme.c.

Referenced by load_config().

#define ENTER   0

Definition at line 200 of file app_meetme.c.

Referenced by conf_play(), and conf_run().

#define LEAVE   1

Definition at line 201 of file app_meetme.c.

Referenced by conf_play().

#define MEETME_DELAYDETECTENDTALK   1000

Definition at line 184 of file app_meetme.c.

Referenced by conf_run().

#define MEETME_DELAYDETECTTALK   300

Definition at line 183 of file app_meetme.c.

Referenced by conf_run().

#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

Definition at line 203 of file app_meetme.c.

Referenced by conf_free(), and recordthread().

#define MEETME_RECORD_TERMINATE   2

Definition at line 205 of file app_meetme.c.

Referenced by conf_free(), and recordthread().


Enumeration Type Documentation

anonymous enum

Enumerator:
OPT_ARG_WAITMARKED 
OPT_ARG_ARRAY_SIZE 

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

Enumerator:
VOL_UP 
VOL_DOWN 

Definition at line 186 of file app_meetme.c.

00186                    {
00187    VOL_UP,
00188    VOL_DOWN,
00189 };


Function Documentation

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(&params, "|");
02071       command = strsep(&params, "|");
02072       caller = strsep(&params, "|");
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.

Returns:
a short description of your 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;
 }

Returns:
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.

Returns:
int Always 0.

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.

Returns:
The return value is not used.

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).

Returns:
Zero on success, or non-zero on error.

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.

Returns:
The module's usecount.

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 }


Variable Documentation

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.

LOCAL_USER_DECL

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.

STANDARD_LOCAL_USER

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.


Generated on Sat Sep 16 05:47:49 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7