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: 170979 $")
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) {
00144 if (*tmp2 == '&') {
00145 num_dials++;
00146 }
00147 tmp2++;
00148 }
00149
00150 if (!(dial_list = ast_calloc(num_dials, sizeof(struct ast_dial *)))) {
00151 ast_log(LOG_ERROR, "Can't allocate %ld bytes for dial list\n", (long)(sizeof(struct ast_dial *) * num_dials));
00152 ast_module_user_remove(u);
00153 return -1;
00154 }
00155
00156
00157 while ((tech = strsep(&tmp, "&"))) {
00158 struct ast_dial *dial = NULL;
00159
00160
00161 if (!strcasecmp(tech, originator))
00162 continue;
00163
00164
00165 if (!(resource = strchr(tech, '/'))) {
00166 ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
00167 continue;
00168 }
00169
00170 *resource++ = '\0';
00171
00172
00173 if (!(dial = ast_dial_create())) {
00174 ast_log(LOG_WARNING, "Failed to create dialing structure.\n");
00175 continue;
00176 }
00177
00178
00179 ast_dial_append(dial, tech, resource);
00180
00181
00182 ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, meetmeopts);
00183
00184
00185 ast_dial_run(dial, chan, 1);
00186
00187
00188 dial_list[pos++] = dial;
00189 }
00190
00191 if (!ast_test_flag(&flags, PAGE_QUIET)) {
00192 res = ast_streamfile(chan, "beep", chan->language);
00193 if (!res)
00194 res = ast_waitstream(chan, "");
00195 }
00196
00197 if (!res) {
00198
00199 snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%s%sqxd", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"),
00200 (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
00201 if (ast_test_flag(&flags, PAGE_ANNOUNCE) && !ast_strlen_zero(flag_args[OPT_ARG_ANNOUNCE]) &&
00202 !ast_test_flag(&flags, PAGE_NOCALLERANNOUNCE)) {
00203 snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%s%sqxdG(%s)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"),
00204 (ast_test_flag(&flags, PAGE_RECORD) ? "r" : ""), flag_args[OPT_ARG_ANNOUNCE] );
00205 }
00206 pbx_exec(chan, app, meetmeopts);
00207 }
00208
00209
00210 for (i = 0; i < pos; i++) {
00211 struct ast_dial *dial = dial_list[i];
00212
00213
00214 ast_dial_join(dial);
00215
00216
00217 ast_dial_hangup(dial);
00218
00219
00220 ast_dial_destroy(dial);
00221 }
00222
00223 ast_free(dial_list);
00224 ast_module_user_remove(u);
00225
00226 return -1;
00227 }
00228
00229 static int unload_module(void)
00230 {
00231 int res;
00232
00233 res = ast_unregister_application(app_page);
00234
00235 ast_module_user_hangup_all();
00236
00237 return res;
00238 }
00239
00240 static int load_module(void)
00241 {
00242 return ast_register_application(app_page, page_exec, page_synopsis, page_descrip);
00243 }
00244
00245 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Page Multiple Phones");
00246