00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 168608 $")
00036
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <unistd.h>
00040 #include <string.h>
00041 #include <errno.h>
00042
00043 #include "asterisk/options.h"
00044 #include "asterisk/logger.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/pbx.h"
00047 #include "asterisk/module.h"
00048 #include "asterisk/file.h"
00049 #include "asterisk/app.h"
00050 #include "asterisk/chanvars.h"
00051 #include "asterisk/utils.h"
00052 #include "asterisk/dial.h"
00053 #include "asterisk/devicestate.h"
00054
00055 static const char *app_page= "Page";
00056
00057 static const char *page_synopsis = "Pages phones";
00058
00059 static const char *page_descrip =
00060 "Page(Technology/Resource&Technology2/Resource2[|options])\n"
00061 " Places outbound calls to the given technology / resource and dumps\n"
00062 "them into a conference bridge as muted participants. The original\n"
00063 "caller is dumped into the conference as a speaker and the room is\n"
00064 "destroyed when the original caller leaves. Valid options are:\n"
00065 " d - full duplex audio\n"
00066 " q - quiet, do not play beep to caller\n"
00067 " r - record the page into a file (see 'r' for app_meetme)\n"
00068 " A(x) - Play an announce simultaneously to all paged participants,\n"
00069 " and also to the original caller. Use 'x' as the file.\n"
00070 " n - Not to play simultaneous announce to caller (implies A(x)).\n";
00071
00072
00073 enum {
00074 PAGE_DUPLEX = (1 << 0),
00075 PAGE_QUIET = (1 << 1),
00076 PAGE_RECORD = (1 << 2),
00077 PAGE_ANNOUNCE = (1 << 3),
00078 PAGE_NOCALLERANNOUNCE = (1 << 4),
00079 } page_opt_flags;
00080
00081 enum {
00082 OPT_ARG_ANNOUNCE = 0,
00083 OPT_ARG_ARRAY_SIZE = 1,
00084 };
00085
00086 AST_APP_OPTIONS(page_opts, {
00087 AST_APP_OPTION('d', PAGE_DUPLEX),
00088 AST_APP_OPTION('q', PAGE_QUIET),
00089 AST_APP_OPTION('r', PAGE_RECORD),
00090 AST_APP_OPTION_ARG('A', PAGE_ANNOUNCE, OPT_ARG_ANNOUNCE),
00091 AST_APP_OPTION('n', PAGE_NOCALLERANNOUNCE),
00092 });
00093
00094
00095 static int page_exec(struct ast_channel *chan, void *data)
00096 {
00097 struct ast_module_user *u;
00098 char *options, *tech, *resource, *tmp, *tmp2;
00099 char meetmeopts[128], originator[AST_CHANNEL_NAME];
00100 struct ast_flags flags = { 0 };
00101 char *flag_args[OPT_ARG_ARRAY_SIZE];
00102 unsigned int confid = ast_random();
00103 struct ast_app *app;
00104 int res = 0, pos = 0, i = 0;
00105 struct ast_dial **dial_list;
00106 unsigned int num_dials;
00107
00108 if (ast_strlen_zero(data)) {
00109 ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
00110 return -1;
00111 }
00112
00113 u = ast_module_user_add(chan);
00114
00115 if (!(app = pbx_findapp("MeetMe"))) {
00116 ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
00117 ast_module_user_remove(u);
00118 return -1;
00119 };
00120
00121 options = ast_strdupa(data);
00122
00123 ast_copy_string(originator, chan->name, sizeof(originator));
00124 if ((tmp = strchr(originator, '-')))
00125 *tmp = '\0';
00126
00127 tmp = strsep(&options, "|");
00128 if (options)
00129 ast_app_parse_options(page_opts, &flags, flag_args, options);
00130
00131 if (ast_test_flag(&flags, PAGE_ANNOUNCE) && !ast_strlen_zero(flag_args[OPT_ARG_ANNOUNCE])) {
00132 snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe|%ud|%s%sqxdw(5)G(%s)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
00133 (ast_test_flag(&flags, PAGE_RECORD) ? "r" : ""), flag_args[OPT_ARG_ANNOUNCE] );
00134
00135 } else {
00136 snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe|%ud|%s%sqxdw(5)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
00137 (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
00138 }
00139
00140
00141 num_dials = 1;
00142 tmp2 = tmp;
00143 while (*tmp2 && *tmp2++ == '&') {
00144 num_dials++;
00145 }
00146
00147 if (!(dial_list = ast_calloc(num_dials, sizeof(void *)))) {
00148 ast_log(LOG_ERROR, "Can't allocate %ld bytes for dial list\n", (long)(sizeof(void *) * num_dials));
00149 ast_module_user_remove(u);
00150 return -1;
00151 }
00152
00153
00154 while ((tech = strsep(&tmp, "&"))) {
00155 struct ast_dial *dial = NULL;
00156
00157
00158 if (!strcasecmp(tech, originator))
00159 continue;
00160
00161
00162 if (!(resource = strchr(tech, '/'))) {
00163 ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
00164 continue;
00165 }
00166
00167 *resource++ = '\0';
00168
00169
00170 if (!(dial = ast_dial_create())) {
00171 ast_log(LOG_WARNING, "Failed to create dialing structure.\n");
00172 continue;
00173 }
00174
00175
00176 ast_dial_append(dial, tech, resource);
00177
00178
00179 ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, meetmeopts);
00180
00181
00182 ast_dial_run(dial, chan, 1);
00183
00184
00185 dial_list[pos++] = dial;
00186 }
00187
00188 if (!ast_test_flag(&flags, PAGE_QUIET)) {
00189 res = ast_streamfile(chan, "beep", chan->language);
00190 if (!res)
00191 res = ast_waitstream(chan, "");
00192 }
00193
00194 if (!res) {
00195
00196 snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%s%sqxd", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"),
00197 (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
00198 if (ast_test_flag(&flags, PAGE_ANNOUNCE) && !ast_strlen_zero(flag_args[OPT_ARG_ANNOUNCE]) &&
00199 !ast_test_flag(&flags, PAGE_NOCALLERANNOUNCE)) {
00200 snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%s%sqxdG(%s)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"),
00201 (ast_test_flag(&flags, PAGE_RECORD) ? "r" : ""), flag_args[OPT_ARG_ANNOUNCE] );
00202 }
00203 pbx_exec(chan, app, meetmeopts);
00204 }
00205
00206
00207 for (i = 0; i < pos; i++) {
00208 struct ast_dial *dial = dial_list[i];
00209
00210
00211 ast_dial_join(dial);
00212
00213
00214 ast_dial_hangup(dial);
00215
00216
00217 ast_dial_destroy(dial);
00218 }
00219
00220 ast_free(dial_list);
00221 ast_module_user_remove(u);
00222
00223 return -1;
00224 }
00225
00226 static int unload_module(void)
00227 {
00228 int res;
00229
00230 res = ast_unregister_application(app_page);
00231
00232 ast_module_user_hangup_all();
00233
00234 return res;
00235 }
00236
00237 static int load_module(void)
00238 {
00239 return ast_register_application(app_page, page_exec, page_synopsis, page_descrip);
00240 }
00241
00242 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Page Multiple Phones");
00243