Index: apps/app_meetme.c =================================================================== --- apps/app_meetme.c (revision 61802) +++ apps/app_meetme.c (working copy) @@ -74,8 +74,17 @@ #define SLA_CONFIG_FILE "sla.conf" /*! each buffer is 20ms, so this is 640ms total */ -#define DEFAULT_AUDIO_BUFFERS 32 +#define DEFAULT_AUDIO_BUFFERS 32 +/*! Column names for RealTime storage of conferences */ +#define DEFAULT_CONF_COL "confno" +#define DEFAULT_USER_PIN_COL "pin" +#define DEFAULT_ADMIN_PIN_COL "adminpin" +#define DEFAULT_USER_OPTS_COL "" +#define DEFAULT_MOD_OPTS_COL "" +/*! String format for scheduled conferences */ +#define DATE_FORMAT "%Y-%m-%d %H:%M:%S" + enum { ADMINFLAG_MUTED = (1 << 1), /*!< User is muted */ ADMINFLAG_SELFMUTED = (1 << 2), /*!< User muted self */ @@ -209,6 +218,22 @@ static const char *slastation_synopsis = "Shared Line Appearance Station"; static const char *slatrunk_synopsis = "Shared Line Appearance Trunk"; +/* RealTime database column names */ +static char rt_conf_column[AST_MAX_EXTENSION]; +static char rt_user_pin_column[AST_MAX_EXTENSION]; +static char rt_admin_pin_column[AST_MAX_EXTENSION]; +static char rt_user_opts_column[AST_MAX_EXTENSION]; +static char rt_admin_opts_column[AST_MAX_EXTENSION]; +static char rt_members_column[AST_MAX_EXTENSION]; + +/* Lookup RealTime conferences based on confno and current time */ +static int rt_schedule; +static int fuzzystart; +static int earlyalert; + +/* Log participant count to the RealTime backend */ +static int rt_log_members; + static const char *descrip = " MeetMe([confno][,[options][,pin]]): Enters the user into a specified MeetMe\n" "conference. If the conference number is omitted, the user will be prompted\n" @@ -939,7 +964,8 @@ return RESULT_SUCCESS; } else return RESULT_SHOWUSAGE; - ast_log(LOG_DEBUG, "Cmdline: %s\n", cmdline); + if (option_debug) + ast_log(LOG_DEBUG, "Cmdline: %s\n", cmdline); admin_exec(NULL, cmdline); return 0; @@ -1454,10 +1480,11 @@ user->adminflags = (confflags & CONFFLAG_STARTMUTED) ? ADMINFLAG_SELFMUTED : 0; user->talking = -1; conf->users++; - /* Update table */ - snprintf(members, sizeof(members), "%d", conf->users); - ast_update_realtime("meetme", "confno", conf->confno, "members", members , NULL); - + if (rt_log_members) { + /* Update table */ + snprintf(members, sizeof(members), "%d", conf->users); + ast_update_realtime("meetme", rt_conf_column, conf->confno, rt_members_column, members , NULL); + } /* This device changed state now - if this is the first user */ if (conf->users == 1) ast_device_state_changed("meetme:%s", conf->confno); @@ -1638,7 +1665,8 @@ ast_mutex_unlock(&conf->playlock); goto outrun; } - ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf); + if (option_debug) + ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf); if (!sent_event) { manager_event(EVENT_FLAG_CALL, "MeetmeJoin", @@ -2242,9 +2270,11 @@ } conf->users--; - /* Update table */ - snprintf(members, sizeof(members), "%d", conf->users); - ast_update_realtime("meetme", "confno", conf->confno, "members", members, NULL); + if (rt_log_members){ + /* Update table */ + snprintf(members, sizeof(members), "%d", conf->users); + ast_update_realtime("meetme", rt_conf_column, conf->confno, rt_members_column, members, NULL); + } if (confflags & CONFFLAG_MARKEDUSER) conf->markedusers--; /* Remove ourselves from the list */ @@ -2265,7 +2295,7 @@ } static struct ast_conference *find_conf_realtime(struct ast_channel *chan, char *confno, int make, int dynamic, - char *dynamic_pin, size_t pin_buf_len, int refcount, struct ast_flags *confflags) + char *dynamic_pin, size_t pin_buf_len, int refcount, struct ast_flags *confflags, char *optargs[], int *too_early) { struct ast_variable *var; struct ast_conference *cnf; @@ -2283,22 +2313,82 @@ if (!cnf) { char *pin = NULL, *pinadmin = NULL; /* For temp use */ + time_t now; + char currenttime[32]=""; + char startTime[32]=""; + char eatime[32]=""; + char userOpts[32]=""; + char adminOpts[32]=""; + struct tm *l_time, *ea_time; - var = ast_load_realtime("meetme", "confno", confno, NULL); + if (rt_schedule) { + time(&now); + + if (fuzzystart) + now += fuzzystart; + + + l_time = localtime(&now); + strftime(currenttime, sizeof(currenttime), DATE_FORMAT, l_time); + + if (earlyalert){ + now += earlyalert; + ea_time = localtime(&now); + strftime(eatime, sizeof(eatime), DATE_FORMAT, ea_time); + } + else + { + ea_time = localtime(&now); + strftime(eatime, sizeof(eatime), DATE_FORMAT, ea_time); + } + + if (option_debug) + ast_log(LOG_DEBUG, "Looking for conference %s that starts after %s\n", confno, eatime); + + var = ast_load_realtime("meetme", rt_conf_column, + confno, "startTime<= ", eatime, "endTime>= ", + currenttime, NULL); + } + else + var = ast_load_realtime("meetme", rt_conf_column , confno, NULL); + + if (!var) return NULL; while (var) { - if (!strcasecmp(var->name, "pin")) { + if (!strcasecmp(var->name, rt_user_pin_column)) { pin = ast_strdupa(var->value); - } else if (!strcasecmp(var->name, "adminpin")) { + } else if (!strcasecmp(var->name, rt_admin_pin_column)) { pinadmin = ast_strdupa(var->value); - } + } else if (!strcasecmp(var->name, rt_user_opts_column)) { + ast_copy_string(userOpts, var->value, sizeof(userOpts)); + } else if (!strcasecmp(var->name, rt_admin_opts_column)) { + ast_copy_string(adminOpts, var->value, sizeof(adminOpts)); + } else if (!strcasecmp(var->name, "startTime")) { + ast_copy_string(startTime, var->value, sizeof(startTime)); + } + var = var->next; + } + ast_variables_destroy(var); + if (earlyalert){ + if (strcmp(startTime, currenttime) > 0){ + /* Announce that the caller is early and exit */ + if (!ast_streamfile(chan, "conf-has-not-started", chan->language)) + ast_waitstream(chan, ""); + *too_early = 1; + return NULL; + } + } + + /*if (rt_schedule) + ast_app_parse_options(meetme_opts, confflags, optargs, userOpts); */ + cnf = build_conf(confno, pin ? pin : "", pinadmin ? pinadmin : "", make, dynamic, refcount); } @@ -2384,7 +2474,8 @@ } } if (!var) { - ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno); + if (option_debug) + ast_log(LOG_DEBUG, "%s isn't a valid conference\n", confno); } ast_config_destroy(cfg); } @@ -2621,17 +2712,21 @@ cnf = find_conf(chan, confno, 1, dynamic, the_pin, sizeof(the_pin), 1, &confflags); if (!cnf) { + int too_early = 0; cnf = find_conf_realtime(chan, confno, 1, dynamic, - the_pin, sizeof(the_pin), 1, &confflags); + the_pin, sizeof(the_pin), 1, &confflags, optargs, &too_early); + if (rt_schedule && too_early) + allowretry = 0; } if (!cnf) { - res = ast_streamfile(chan, "conf-invalid", chan->language); - if (!res) - ast_waitstream(chan, ""); - res = -1; - if (allowretry) + if (allowretry){ confno[0] = '\0'; + res = ast_streamfile(chan, "conf-invalid", chan->language); + if (!res) + ast_waitstream(chan, ""); + res = -1; + } } else { if ((!ast_strlen_zero(cnf->pin) && !ast_test_flag(&confflags, CONFFLAG_ADMIN)) || @@ -3045,8 +3140,23 @@ struct ast_config *cfg; const char *val; - audio_buffers = DEFAULT_AUDIO_BUFFERS; + audio_buffers = DEFAULT_AUDIO_BUFFERS; + /* Set RT column names to their defaults */ + ast_copy_string(rt_conf_column, DEFAULT_CONF_COL, sizeof(rt_conf_column)); + ast_copy_string(rt_user_pin_column, DEFAULT_CONF_COL, sizeof(rt_user_pin_column)); + ast_copy_string(rt_admin_pin_column, DEFAULT_CONF_COL, sizeof(rt_admin_pin_column)); + ast_copy_string(rt_user_opts_column, DEFAULT_CONF_COL, sizeof(rt_user_opts_column)); + ast_copy_string(rt_admin_opts_column, DEFAULT_CONF_COL, sizeof(rt_admin_opts_column)); + + /* Scheduling support is off by default */ + rt_schedule = 0; + fuzzystart = 0; + earlyalert = 0; + + /* Logging of participants defaults to ON for compatibility reasons */ + rt_log_members = 1; + if (!(cfg = ast_config_load(CONFIG_FILE_NAME))) return; @@ -3062,6 +3172,42 @@ if (audio_buffers != DEFAULT_AUDIO_BUFFERS) ast_log(LOG_NOTICE, "Audio buffers per channel set to %d\n", audio_buffers); } + if ((val = ast_variable_retrieve(cfg, "general", "rt_confno"))) { + ast_copy_string(rt_conf_column, val, sizeof(rt_conf_column)); + } + if ((val = ast_variable_retrieve(cfg, "general", "rt_upin"))) { + ast_copy_string(rt_user_pin_column, val, sizeof(rt_user_pin_column)); + } + if ((val = ast_variable_retrieve(cfg, "general", "rt_mpin"))) { + ast_copy_string(rt_admin_pin_column, val, sizeof(rt_admin_pin_column)); + } + if ((val = ast_variable_retrieve(cfg, "general", "rt_uflags"))) { + ast_copy_string(rt_user_opts_column, val, sizeof(rt_user_opts_column)); + } + if ((val = ast_variable_retrieve(cfg, "general", "rt_mflags"))) { + ast_copy_string(rt_admin_opts_column, val, sizeof(rt_admin_opts_column)); + } + if ((val = ast_variable_retrieve(cfg, "general", "rt_members"))) { + ast_copy_string(rt_members_column, val, sizeof(rt_members_column)); + } + if ((val = ast_variable_retrieve(cfg, "general", "schedule"))) { + rt_schedule = ast_true(val) ? 1 : 0; + } + if ((val = ast_variable_retrieve(cfg, "general", "logmembercount"))) { + rt_log_members = ast_true(val) ? 1 : 0; + } + if ((val = ast_variable_retrieve(cfg, "general", "fuzzystart"))) { + if ((sscanf(val, "%d", &fuzzystart) != 1)) { + ast_log(LOG_WARNING, "fuzzystart must be a number, not '%s'\n", val); + fuzzystart = 0; + } + } + if ((val = ast_variable_retrieve(cfg, "general", "earlyalert"))) { + if ((sscanf(val, "%d", &earlyalert) != 1)) { + ast_log(LOG_WARNING, "earlyalert must be a number, not '%s'\n", val); + earlyalert = 0; + } + } ast_config_destroy(cfg); } Index: configs/meetme.conf.sample =================================================================== --- configs/meetme.conf.sample (revision 61802) +++ configs/meetme.conf.sample (working copy) @@ -12,7 +12,22 @@ ; source, but can also allow for latency in hearing ; the audio from the speaker. Minimum value is 2, ; maximum value is 32. + +; Optionally change the names of columns used for RealTime MeetMe +;rtconfno=confno ; Name of the database column that holds the conference # +;rtupin=pin ; Name of the database column that holds the user pin +;rtmpin=adminpin ; Name of the database column that holds the mod pin +;rtuflags=uFlags ; Name of the database column that holds conf user options +;rtmflags=mFlags ; Name of the database column that holds conf mod options +;rt_members=members ; Name of the column to hold the participant count ; +;schedule=yes ; Lookup RT conferences based on time. Default is no +;logmembercount=no ; Update the DB with conference participant count. Default is yes +;fuzzystart=30 ; Allow callers to join X seconds early. Default is 0 +;earlyalert=300 ; Inform callers if they calll X seconds before a conference. + ; is scheduled to start. Should not be used with fuzzy start. + ; Default is 0 + [rooms] ; ; Usage is conf => confno[,pin][,adminpin]