aboutsummaryrefslogtreecommitdiffstats
path: root/apps/app_meetme.c
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-11-08 23:19:30 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-11-08 23:19:30 +0000
commit9c77ba7054469eeb54b9b572795b6b90f8f17adf (patch)
tree15c046b2e6a45b6a38de35acb2ffa457e633aaa5 /apps/app_meetme.c
parent28133cd31b175ba7fd6524accef381b86daa2148 (diff)
issues #3599 and #4252
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@7033 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_meetme.c')
-rwxr-xr-xapps/app_meetme.c129
1 files changed, 98 insertions, 31 deletions
diff --git a/apps/app_meetme.c b/apps/app_meetme.c
index 55313c353..9b4c618be 100755
--- a/apps/app_meetme.c
+++ b/apps/app_meetme.c
@@ -55,17 +55,17 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/say.h"
#include "asterisk/utils.h"
-static char *tdesc = "MeetMe conference bridge";
+static const char *tdesc = "MeetMe conference bridge";
-static char *app = "MeetMe";
-static char *app2 = "MeetMeCount";
-static char *app3 = "MeetMeAdmin";
+static const char *app = "MeetMe";
+static const char *app2 = "MeetMeCount";
+static const char *app3 = "MeetMeAdmin";
-static char *synopsis = "MeetMe conference bridge";
-static char *synopsis2 = "MeetMe participant count";
-static char *synopsis3 = "MeetMe conference Administration";
+static const char *synopsis = "MeetMe conference bridge";
+static const char *synopsis2 = "MeetMe participant count";
+static const char *synopsis3 = "MeetMe conference Administration";
-static char *descrip =
+static const char *descrip =
" MeetMe([confno][,[options][,pin]]): Enters the user into a specified MeetMe conference.\n"
"If the conference number is omitted, the user will be prompted to enter\n"
"one. \n"
@@ -102,14 +102,14 @@ static char *descrip =
" digit extension ${MEETME_EXIT_CONTEXT} or the current context\n"
" if that variable is not defined.\n";
-static char *descrip2 =
+static const char *descrip2 =
" MeetMeCount(confno[|var]): Plays back the number of users in the specified\n"
"MeetMe conference. If var is specified, playback will be skipped and the value\n"
"will be returned in the variable. Upon app completion, MeetMeCount will hangup the\n"
"channel, unless priority n+1 exists, in which case priority progress will continue.\n"
"A ZAPTEL INTERFACE MUST BE INSTALLED FOR CONFERENCING FUNCTIONALITY.\n";
-static char *descrip3 =
+static const char *descrip3 =
" MeetMeAdmin(confno,command[,user]): Run admin command for conference\n"
" 'e' -- Eject last user that joined\n"
" 'k' -- Kick one user out of conference\n"
@@ -122,6 +122,8 @@ static char *descrip3 =
" 'N' -- Mute entire conference (except admin)\n"
"";
+#define CONFIG_FILE_NAME "meetme.conf"
+
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
@@ -169,8 +171,14 @@ struct ast_conf_user {
struct volume listen;
};
-#define ADMINFLAG_MUTED (1 << 1) /* User is muted */
-#define ADMINFLAG_KICKME (1 << 2) /* User is kicked */
+static int audio_buffers; /* The number of audio buffers to be allocated on pseudo channels
+ when in a conference
+ */
+
+#define DEFAULT_AUDIO_BUFFERS 32 /* each buffer is 20ms, so this is 640ms total */
+
+#define ADMINFLAG_MUTED (1 << 1) /* User is muted */
+#define ADMINFLAG_KICKME (1 << 2) /* User is kicked */
#define MEETME_DELAYDETECTTALK 300
#define MEETME_DELAYDETECTENDTALK 1000
@@ -706,16 +714,34 @@ static char conf_usage[] =
" Executes a command for the conference or on a conferee\n";
static struct ast_cli_entry cli_conf = {
- { "meetme", NULL, NULL }, conf_cmd,
- "Execute a command on a conference or conferee", conf_usage, complete_confcmd };
+ {"meetme", NULL, NULL }, conf_cmd,
+ "Execute a command on a conference or conferee", conf_usage, complete_confcmd};
-static void conf_flush(int fd)
+static void conf_flush(int fd, struct ast_channel *chan)
{
int x;
+ /* read any frames that may be waiting on the channel
+ and throw them away
+ */
+ if (chan) {
+ struct ast_frame *f;
+
+ /* when no frames are available, this will wait
+ for 1 millisecond maximum
+ */
+ while (ast_waitfor(chan, 1)) {
+ f = ast_read(chan);
+ if (f)
+ ast_frfree(f);
+ }
+ }
+
+ /* flush any data sitting in the pseudo channel */
x = ZT_FLUSH_ALL;
if (ioctl(fd, ZT_FLUSH, &x))
ast_log(LOG_WARNING, "Error flushing channel\n");
+
}
/* Remove the conference from the list and free it.
@@ -960,7 +986,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
bi.bufsize = CONF_SIZE/2;
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
- bi.numbufs = 4;
+ bi.numbufs = audio_buffers;
if (ioctl(fd, ZT_SET_BUFINFO, &bi)) {
ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
close(fd);
@@ -1042,7 +1068,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
ast_mutex_unlock(&conflock);
- conf_flush(fd);
+ conf_flush(fd, chan);
if (confflags & CONFFLAG_AGI) {
/* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND)
@@ -1273,8 +1299,15 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
}
}
if (using_pseudo) {
- /* Carefully write */
- careful_write(fd, f->data, f->datalen);
+ /* Absolutely do _not_ use careful_write here...
+ it is important that we read data from the channel
+ as fast as it arrives, and feed it into the conference.
+ The buffering in the pseudo channel will take care of any
+ timing differences, unless they are so drastic as to lose
+ audio frames (in which case carefully writing would only
+ have delayed the audio even further).
+ */
+ write(fd, f->data, f->datalen);
}
} else if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) {
char tmp[2];
@@ -1451,7 +1484,8 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int c
ast_mutex_unlock(&conflock);
goto outrun;
}
- conf_flush(fd);
+
+ conf_flush(fd, chan);
} else if (option_debug) {
ast_log(LOG_DEBUG,
"Got unrecognized frame on channel %s, f->frametype=%d,f->subclass=%d\n",
@@ -1597,9 +1631,9 @@ static struct ast_conference *find_conf(struct ast_channel *chan, char *confno,
}
} else {
/* Check the config */
- cfg = ast_config_load("meetme.conf");
+ cfg = ast_config_load(CONFIG_FILE_NAME);
if (!cfg) {
- ast_log(LOG_WARNING, "No meetme.conf file :(\n");
+ ast_log(LOG_WARNING, "No %s file :(\n", CONFIG_FILE_NAME);
return NULL;
}
var = ast_variable_browse(cfg, "rooms");
@@ -1748,28 +1782,24 @@ static int conf_exec(struct ast_channel *chan, void *data)
if (retrycnt > 3)
allowretry = 0;
if (empty) {
- int i, map[1024];
+ int i, map[1024] = { 0, };
struct ast_config *cfg;
struct ast_variable *var;
int confno_int;
- memset(map, 0, sizeof(map));
-
ast_mutex_lock(&conflock);
- cnf = confs;
- while (cnf) {
+ for (cnf = confs; cnf; cnf = cnf->next) {
if (sscanf(cnf->confno, "%d", &confno_int) == 1) {
/* Disqualify in use conference */
if (confno_int >= 0 && confno_int < 1024)
map[confno_int]++;
}
- cnf = cnf->next;
}
ast_mutex_unlock(&conflock);
/* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */
if ((empty_no_pin) || (!dynamic)) {
- cfg = ast_config_load("meetme.conf");
+ cfg = ast_config_load(CONFIG_FILE_NAME);
if (cfg) {
var = ast_variable_browse(cfg, "rooms");
while (var) {
@@ -1820,9 +1850,10 @@ static int conf_exec(struct ast_channel *chan, void *data)
ast_config_destroy(cfg);
}
}
+
/* Select first conference number not in use */
if (ast_strlen_zero(confno) && dynamic) {
- for (i=0;i<1024;i++) {
+ for (i = 0; i < sizeof(map) / sizeof(map[0]); i++) {
if (!map[i]) {
snprintf(confno, sizeof(confno), "%d", i);
break;
@@ -1847,6 +1878,7 @@ static int conf_exec(struct ast_channel *chan, void *data)
}
}
}
+
while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) {
/* Prompt user for conference number */
res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0);
@@ -2116,6 +2148,32 @@ static void *recordthread(void *args)
pthread_exit(0);
}
+static void load_config(void)
+{
+ struct ast_config *cfg;
+ char *val;
+
+ audio_buffers = DEFAULT_AUDIO_BUFFERS;
+
+ if (!(cfg = ast_config_load(CONFIG_FILE_NAME)))
+ return;
+
+ if ((val = ast_variable_retrieve(cfg, "general", "audiobuffers"))) {
+ if ((sscanf(val, "%d", &audio_buffers) != 1)) {
+ ast_log(LOG_WARNING, "audiobuffers setting must be a number, not '%s'\n", val);
+ audio_buffers = DEFAULT_AUDIO_BUFFERS;
+ } else if ((audio_buffers < ZT_DEFAULT_NUM_BUFS) || (audio_buffers > ZT_MAX_NUM_BUFS)) {
+ ast_log(LOG_WARNING, "audiobuffers setting must be between %d and %d\n",
+ ZT_DEFAULT_NUM_BUFS, ZT_MAX_NUM_BUFS);
+ audio_buffers = DEFAULT_AUDIO_BUFFERS;
+ }
+ if (audio_buffers != DEFAULT_AUDIO_BUFFERS)
+ ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers);
+ }
+
+ ast_config_destroy(cfg);
+}
+
int unload_module(void)
{
int res;
@@ -2135,6 +2193,8 @@ int load_module(void)
{
int res;
+ load_config();
+
res = ast_cli_register(&cli_show_confs);
res |= ast_cli_register(&cli_conf);
res |= ast_register_application(app3, admin_exec, synopsis3, descrip3);
@@ -2144,9 +2204,16 @@ int load_module(void)
return res;
}
+int reload(void)
+{
+ load_config();
+
+ return 0;
+}
+
char *description(void)
{
- return tdesc;
+ return (char *) tdesc;
}
int usecount(void)