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: 170981 $")
00036
00037 #include "asterisk/channel.h"
00038 #include "asterisk/pbx.h"
00039 #include "asterisk/module.h"
00040 #include "asterisk/file.h"
00041 #include "asterisk/app.h"
00042 #include "asterisk/chanvars.h"
00043 #include "asterisk/utils.h"
00044 #include "asterisk/devicestate.h"
00045 #include "asterisk/dial.h"
00046
00047 static const char *app_page= "Page";
00048
00049 static const char *page_synopsis = "Pages phones";
00050
00051 static const char *page_descrip =
00052 "Page(Technology/Resource&Technology2/Resource2[,options])\n"
00053 " Places outbound calls to the given technology / resource and dumps\n"
00054 "them into a conference bridge as muted participants. The original\n"
00055 "caller is dumped into the conference as a speaker and the room is\n"
00056 "destroyed when the original caller leaves. Valid options are:\n"
00057 " d - full duplex audio\n"
00058 " q - quiet, do not play beep to caller\n"
00059 " r - record the page into a file (see 'r' for app_meetme)\n"
00060 " s - only dial channel if devicestate says it is not in use\n";
00061
00062 enum {
00063 PAGE_DUPLEX = (1 << 0),
00064 PAGE_QUIET = (1 << 1),
00065 PAGE_RECORD = (1 << 2),
00066 PAGE_SKIP = (1 << 3),
00067 } page_opt_flags;
00068
00069 AST_APP_OPTIONS(page_opts, {
00070 AST_APP_OPTION('d', PAGE_DUPLEX),
00071 AST_APP_OPTION('q', PAGE_QUIET),
00072 AST_APP_OPTION('r', PAGE_RECORD),
00073 AST_APP_OPTION('s', PAGE_SKIP),
00074 });
00075
00076
00077 static int page_exec(struct ast_channel *chan, void *data)
00078 {
00079 char *options, *tech, *resource, *tmp, *tmp2;
00080 char meetmeopts[88], originator[AST_CHANNEL_NAME], *opts[0];
00081 struct ast_flags flags = { 0 };
00082 unsigned int confid = ast_random();
00083 struct ast_app *app;
00084 int res = 0, pos = 0, i = 0;
00085 struct ast_dial **dial_list;
00086 unsigned int num_dials;
00087
00088 if (ast_strlen_zero(data)) {
00089 ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
00090 return -1;
00091 }
00092
00093 if (!(app = pbx_findapp("MeetMe"))) {
00094 ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
00095 return -1;
00096 };
00097
00098 options = ast_strdupa(data);
00099
00100 ast_copy_string(originator, chan->name, sizeof(originator));
00101 if ((tmp = strchr(originator, '-')))
00102 *tmp = '\0';
00103
00104 tmp = strsep(&options, ",");
00105 if (options)
00106 ast_app_parse_options(page_opts, &flags, opts, options);
00107
00108 snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe,%ud,%s%sqxdw(5)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
00109 (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
00110
00111
00112 num_dials = 1;
00113 tmp2 = tmp;
00114 while (*tmp2) {
00115 if (*tmp2 == '&') {
00116 num_dials++;
00117 }
00118 tmp2++;
00119 }
00120
00121 if (!(dial_list = ast_calloc(num_dials, sizeof(struct ast_dial *)))) {
00122 ast_log(LOG_ERROR, "Can't allocate %ld bytes for dial list\n", (long)(sizeof(struct ast_dial *) * num_dials));
00123 return -1;
00124 }
00125
00126
00127 while ((tech = strsep(&tmp, "&"))) {
00128 int state = 0;
00129 struct ast_dial *dial = NULL;
00130
00131
00132 if (!strcasecmp(tech, originator))
00133 continue;
00134
00135
00136 if (!(resource = strchr(tech, '/'))) {
00137 ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
00138 continue;
00139 }
00140
00141
00142 if (ast_test_flag(&flags, PAGE_SKIP)) {
00143 state = ast_device_state(tech);
00144 if (state == AST_DEVICE_UNKNOWN) {
00145 ast_log(LOG_WARNING, "Destination '%s' has device state '%s'. Paging anyway.\n", tech, devstate2str(state));
00146 } else if (state != AST_DEVICE_NOT_INUSE) {
00147 ast_log(LOG_WARNING, "Destination '%s' has device state '%s'.\n", tech, devstate2str(state));
00148 continue;
00149 }
00150 }
00151
00152 *resource++ = '\0';
00153
00154
00155 if (!(dial = ast_dial_create())) {
00156 ast_log(LOG_WARNING, "Failed to create dialing structure.\n");
00157 continue;
00158 }
00159
00160
00161 ast_dial_append(dial, tech, resource);
00162
00163
00164 ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, meetmeopts);
00165
00166
00167 ast_dial_run(dial, chan, 1);
00168
00169
00170 dial_list[pos++] = dial;
00171 }
00172
00173 if (!ast_test_flag(&flags, PAGE_QUIET)) {
00174 res = ast_streamfile(chan, "beep", chan->language);
00175 if (!res)
00176 res = ast_waitstream(chan, "");
00177 }
00178
00179 if (!res) {
00180 snprintf(meetmeopts, sizeof(meetmeopts), "%ud,A%s%sqxd", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"),
00181 (ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
00182 pbx_exec(chan, app, meetmeopts);
00183 }
00184
00185
00186 for (i = 0; i < pos; i++) {
00187 struct ast_dial *dial = dial_list[i];
00188
00189
00190 ast_dial_join(dial);
00191
00192
00193 ast_dial_hangup(dial);
00194
00195
00196 ast_dial_destroy(dial);
00197 }
00198
00199 return -1;
00200 }
00201
00202 static int unload_module(void)
00203 {
00204 return ast_unregister_application(app_page);
00205 }
00206
00207 static int load_module(void)
00208 {
00209 return ast_register_application(app_page, page_exec, page_synopsis, page_descrip);
00210 }
00211
00212 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Page Multiple Phones");
00213