2 * Asterisk -- A telephony toolkit for Linux.
4 * ParkAndAnnounce application for Asterisk
5 * Author: Ben Miller <bgmiller@dccinc.com>
6 * With TONS of help from Mark!
8 * Asterisk is Copyrighted as follows
9 * Copyright (C) 1999-2004, Digium, Inc.
11 * Mark Spencer <markster@digium.com>
13 * This program is free software, distributed under the terms of
14 * the GNU General Public License
17 #include <sys/types.h>
18 #include <asterisk/file.h>
19 #include <asterisk/logger.h>
20 #include <asterisk/channel.h>
21 #include <asterisk/channel_pvt.h>
22 #include <asterisk/pbx.h>
23 #include <asterisk/module.h>
24 #include <asterisk/features.h>
25 #include <asterisk/options.h>
26 #include <asterisk/logger.h>
27 #include <asterisk/say.h>
28 #include <asterisk/lock.h>
35 static char *tdesc = "Call Parking and Announce Application";
37 static char *app = "ParkAndAnnounce";
39 static char *synopsis = "Park and Announce";
41 static char *descrip =
42 " ParkAndAnnounce(announce:template|timeout|dial|[return_context]):\n"
43 "Park a call into the parkinglot and announce the call over the console.\n"
44 "announce template: colon seperated list of files to announce, the word PARKED\n"
45 " will be replaced by a say_digits of the ext the call is parked in\n"
46 "timeout: time in seconds before the call returns into the return context.\n"
47 "dial: The app_dial style resource to call to make the announcement. Console/dsp calls the console.\n"
48 "return_context: the goto style label to jump the call back into after timeout. default=prio+1\n";
55 static int parkandannounce_exec(struct ast_channel *chan, void *data)
59 int l, lot, timeout = 0, dres;
60 char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
61 char *template, *tpl_working, *tpl_current;
66 struct ast_channel *dchan;
70 if(!data || (data && !strlen(data))) {
71 ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
78 ast_log(LOG_WARNING, "Out of memory\n");
84 template=strsep(&s,"|");
86 ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
92 timeout = atoi(strsep(&s, "|"));
97 ast_log(LOG_WARNING, "PARK: A dial resouce must be specified i.e: Console/dsp or Zap/g1/5551212\n");
101 dialtech=strsep(&dial, "/");
103 ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
108 if(return_context != NULL) {
109 /* set the return context. Code borrowed from the Goto builtin */
111 working = return_context;
112 context = strsep(&working, "|");
113 exten = strsep(&working, "|");
115 /* Only a priority in this one */
120 priority = strsep(&working, "|");
122 /* Only an extension and priority in this one */
128 if(atoi(priority) < 0) {
129 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
133 /* At this point we have a priority and maybe an extension and a context */
134 chan->priority = atoi(priority);
135 if(exten && strcasecmp(exten, "BYEXTENSION"))
136 strncpy(chan->exten, exten, sizeof(chan->exten)-1);
138 strncpy(chan->context, context, sizeof(chan->context)-1);
139 } else { /* increment the priority by default*/
144 if(option_verbose > 2) {
145 ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
146 if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
147 ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
153 /* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
154 before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
156 ast_masq_park_call(chan, NULL, timeout, &lot);
160 ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
162 /* Now place the call to the extention */
164 dchan = ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name);
167 if(dchan->_state == AST_STATE_UP) {
168 if(option_verbose > 3)
169 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
171 if(option_verbose > 3)
172 ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
173 ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
176 LOCAL_USER_REMOVE(u);
180 ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
182 LOCAL_USER_REMOVE(u);
186 ast_stopstream(dchan);
188 /* now we have the call placed and are ready to play stuff to it */
190 ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
192 tpl_working = template;
193 tpl_current=strsep(&tpl_working, ":");
195 while(tpl_current && looptemp < sizeof(tmp)) {
196 tmp[looptemp]=tpl_current;
198 tpl_current=strsep(&tpl_working,":");
201 for(i=0; i<looptemp; i++) {
202 ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
203 if(!strcmp(tmp[i], "PARKED")) {
204 ast_say_digits(dchan, lot, "", dchan->language);
206 dres = ast_streamfile(dchan, tmp[i], dchan->language);
208 dres = ast_waitstream(dchan, "");
210 ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
216 ast_stopstream(dchan);
219 LOCAL_USER_REMOVE(u);
226 int unload_module(void)
228 STANDARD_HANGUP_LOCALUSERS;
229 return ast_unregister_application(app);
232 int load_module(void)
234 /* return ast_register_application(app, park_exec); */
235 return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
238 char *description(void)
246 STANDARD_USECOUNT(res);
252 return ASTERISK_GPL_KEY;