Skip to content

Commit 4657163

Browse files
app_directory: Add ADSI support to Directory.
This adds optional ADSI support to the Directory application, which allows callers with ADSI CPE to navigate the Directory system significantly faster than is possible using the audio prompts. Callers can see the directory name (and optionally extension) on their screenphone and confirm or reject a match immediately rather than waiting for it to be spelled out, enhancing usability. Resolves: #356
1 parent 8208654 commit 4657163

File tree

1 file changed

+91
-1
lines changed

1 file changed

+91
-1
lines changed

apps/app_directory.c

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "asterisk/say.h"
4040
#include "asterisk/app.h"
4141
#include "asterisk/utils.h"
42+
#include "asterisk/adsi.h"
4243

4344
/*** DOCUMENTATION
4445
<application name="Directory" language="en_US">
@@ -111,12 +112,17 @@
111112
<para>Skip calling the extension, instead set it in the <variable>DIRECTORY_EXTEN</variable>
112113
channel variable.</para>
113114
</option>
115+
<option name="d">
116+
<para>Enable ADSI support for screen phone searching and retrieval
117+
of directory results.</para>
118+
<para>Additionally, the channel must be ADSI-enabled and you must
119+
have an ADSI-compatible (Type III) CPE for this to work.</para>
120+
</option>
114121
</optionlist>
115122
<note><para>Only one of the <replaceable>f</replaceable>, <replaceable>l</replaceable>, or <replaceable>b</replaceable>
116123
options may be specified. <emphasis>If more than one is specified</emphasis>, then Directory will act as
117124
if <replaceable>b</replaceable> was specified. The number
118125
of characters for the user to type defaults to <literal>3</literal>.</para></note>
119-
120126
</parameter>
121127
</syntax>
122128
<description>
@@ -167,6 +173,7 @@ enum {
167173
OPT_ALIAS = (1 << 7),
168174
OPT_CONFIG_FILE = (1 << 8),
169175
OPT_SKIP = (1 << 9),
176+
OPT_ADSI = (1 << 10),
170177
};
171178

172179
enum {
@@ -200,8 +207,72 @@ AST_APP_OPTIONS(directory_app_options, {
200207
AST_APP_OPTION('a', OPT_ALIAS),
201208
AST_APP_OPTION_ARG('c', OPT_CONFIG_FILE, OPT_ARG_FILENAME),
202209
AST_APP_OPTION('s', OPT_SKIP),
210+
AST_APP_OPTION('d', OPT_ADSI), /* (Would've used 'a', but that was taken already) */
203211
});
204212

213+
static int adsi_search_input(struct ast_channel *chan)
214+
{
215+
unsigned char buf[256];
216+
int bytes = 0;
217+
unsigned char keys[6];
218+
219+
memset(keys, 0, sizeof(keys));
220+
221+
bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
222+
bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
223+
bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
224+
bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Query: ***", "");
225+
bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
226+
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Search", "Search", "#", 1);
227+
bytes += ast_adsi_set_keys(buf + bytes, keys);
228+
bytes += ast_adsi_voice_mode(buf + bytes, 0);
229+
230+
ast_debug(3, "Sending ADSI search input screen on %s\n", ast_channel_name(chan));
231+
232+
return ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
233+
}
234+
235+
static int adsi_confirm_match(struct ast_channel *chan, int seq, int total, const char *exten, const char *name, int showexten)
236+
{
237+
unsigned char buf[4096];
238+
int alignments[5] = {ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT, ADSI_JUST_CENT};
239+
char *lines[5] = {NULL, NULL, NULL, NULL, NULL};
240+
int x, bytes = 0;
241+
unsigned char keys[8];
242+
char matchbuf[32];
243+
244+
snprintf(matchbuf, sizeof(matchbuf), "%d of %d", seq + 1, total); /* Make it 1-indexed for user consumption */
245+
246+
lines[0] = " "; /* Leave the first line empty so the following lines stand out more */
247+
lines[1] = matchbuf;
248+
lines[2] = (char*) name;
249+
250+
if (showexten) {
251+
/* If say extension option is set, show it for ADSI as well */
252+
lines[3] = (char*) exten;
253+
}
254+
255+
/* Don't use ast_adsi_print here, this way we can send it all at once instead of in 2 transmissions */
256+
for (x = 0; lines[x]; x++) {
257+
bytes += ast_adsi_display(buf + bytes, ADSI_INFO_PAGE, x + 1, alignments[x], 0, lines[x], "");
258+
}
259+
bytes += ast_adsi_set_line(buf + bytes, ADSI_INFO_PAGE, 1);
260+
261+
keys[3] = ADSI_KEY_APPS + 3;
262+
keys[4] = ADSI_KEY_APPS + 4;
263+
keys[5] = ADSI_KEY_APPS + 5;
264+
/* You might think we only need to set the keys up the first time, but nope, we've got to do it each time. */
265+
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Dial", "Dial", "1", 0);
266+
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Next", "Next", "*", 0);
267+
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 0);
268+
bytes += ast_adsi_set_keys(buf + bytes, keys);
269+
bytes += ast_adsi_voice_mode(buf + bytes, 0);
270+
271+
ast_debug(3, "Sending ADSI confirmation menu for %s\n", name);
272+
273+
return ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
274+
}
275+
205276
static int compare(const char *text, const char *template)
206277
{
207278
char digit;
@@ -374,6 +445,10 @@ static int select_item_seq(struct ast_channel *chan, struct directory_item **ite
374445
for (ptr = items, i = 0; i < count; i++, ptr++) {
375446
item = *ptr;
376447

448+
if (ast_test_flag(flags, OPT_ADSI) && adsi_confirm_match(chan, i, count, item->exten, item->name, ast_test_flag(flags, OPT_SAYEXTENSION))) {
449+
return -1;
450+
}
451+
377452
for (loop = 3 ; loop > 0; loop--) {
378453
if (!res)
379454
res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags);
@@ -933,13 +1008,28 @@ static int directory_exec(struct ast_channel *chan, const char *data)
9331008
}
9341009
digits[7] = digit + '0';
9351010

1011+
if (ast_test_flag(&flags, OPT_ADSI)) {
1012+
if (!ast_adsi_available(chan)) {
1013+
ast_log(LOG_WARNING, "ADSI not available on %s\n", ast_channel_name(chan));
1014+
ast_clear_flag(&flags, OPT_ADSI);
1015+
} else {
1016+
res = ast_adsi_load_session(chan, NULL, 0, 1);
1017+
if (res < 0) {
1018+
return res;
1019+
}
1020+
}
1021+
}
1022+
9361023
if (ast_channel_state(chan) != AST_STATE_UP) {
9371024
if (!ast_test_flag(&flags, OPT_NOANSWER)) {
9381025
/* Otherwise answer unless we're supposed to read while on-hook */
9391026
res = ast_answer(chan);
9401027
}
9411028
}
9421029
for (;;) {
1030+
if (ast_test_flag(&flags, OPT_ADSI) && adsi_search_input(chan)) {
1031+
return -1;
1032+
}
9431033
if (!ast_strlen_zero(dirintro) && !res) {
9441034
res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY);
9451035
} else if (!res) {

0 commit comments

Comments
 (0)