mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 12:36:58 +00:00
Implement keyboard handling, and use it to enter
a number to dial in the 'message' area under the keypad. Now you can make calls using the keypad as a regular phone (or the keyboard for chars not present on the keypad) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@97488 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
#include "asterisk.h" /* ast_strdupa */
|
#include "asterisk.h" /* ast_strdupa */
|
||||||
#include "asterisk/utils.h" /* ast_strdupa */
|
#include "asterisk/utils.h" /* ast_strdupa */
|
||||||
|
#include "console_video.h" /* ast_strdupa */
|
||||||
|
|
||||||
#ifdef HAVE_SDL /* we only use this code if SDL is available */
|
#ifdef HAVE_SDL /* we only use this code if SDL is available */
|
||||||
#include <SDL/SDL.h>
|
#include <SDL/SDL.h>
|
||||||
@@ -180,8 +181,8 @@ static void render_board(struct board *b)
|
|||||||
/* blit all characters */
|
/* blit all characters */
|
||||||
for (i = first_char, col = 0; i < last_char; i++) {
|
for (i = first_char, col = 0; i < last_char; i++) {
|
||||||
int c = b->text[i] - 32; /* XXX first 32 chars are not printable */
|
int c = b->text[i] - 32; /* XXX first 32 chars are not printable */
|
||||||
if (c < 0) /* should not happen, but just in case... */
|
if (c < 0) /* buffer terminator or anything else is a blank */
|
||||||
continue;
|
c = 0;
|
||||||
SDL_BlitSurface(b->font, &b->font_rects[c], b->screen, &dst);
|
SDL_BlitSurface(b->font, &b->font_rects[c], b->screen, &dst);
|
||||||
/* point dst to next char position */
|
/* point dst to next char position */
|
||||||
dst.x += dst.w;
|
dst.x += dst.w;
|
||||||
@@ -195,11 +196,24 @@ static void render_board(struct board *b)
|
|||||||
SDL_UpdateRects(b->screen, 1, b->p_rect); /* Update the screen */
|
SDL_UpdateRects(b->screen, 1, b->p_rect); /* Update the screen */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return the content of a board */
|
||||||
|
const char *read_message(const struct board *b)
|
||||||
|
{
|
||||||
|
return b->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
int reset_board(struct board *b)
|
||||||
|
{
|
||||||
|
memset(b->text, ' ', b->v_w * b->v_h); /* fill with spaces */
|
||||||
|
b->cur_col = 0;
|
||||||
|
b->cur_line = 0;
|
||||||
|
render_board(b);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/* Store the message on the history board
|
/* Store the message on the history board
|
||||||
* and blit on screen if required.
|
* and blit on screen if required.
|
||||||
* XXX now easy. only regular chars
|
* XXX now easy. only regular chars
|
||||||
*/
|
*/
|
||||||
int print_message(struct board *b, const char *s);
|
|
||||||
int print_message(struct board *b, const char *s)
|
int print_message(struct board *b, const char *s)
|
||||||
{
|
{
|
||||||
int i, l, row, col;
|
int i, l, row, col;
|
||||||
@@ -261,12 +275,14 @@ int print_message(struct board *b, const char *s)
|
|||||||
col = 0;
|
col = 0;
|
||||||
break;
|
break;
|
||||||
case '\n': /* move to beginning of next line */
|
case '\n': /* move to beginning of next line */
|
||||||
|
dst[col] = '\0'; /* mark the rest of the line as empty */
|
||||||
col = 0;
|
col = 0;
|
||||||
dst += b->v_w;
|
dst += b->v_w;
|
||||||
break;
|
break;
|
||||||
case '\b': /* one char back */
|
case '\b': /* one char back */
|
||||||
if (col > 0)
|
if (col > 0)
|
||||||
col--;
|
col--;
|
||||||
|
dst[col] = ' '; /* delete current char */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (s[i] < 32) /* signed, so take up to 127 */
|
if (s[i] < 32) /* signed, so take up to 127 */
|
||||||
@@ -280,6 +296,7 @@ int print_message(struct board *b, const char *s)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dst[col] = '\0'; /* the current position is empty */
|
||||||
b->cur_col = col;
|
b->cur_col = col;
|
||||||
/* everything is printed now, must do the rendering */
|
/* everything is printed now, must do the rendering */
|
||||||
render_board(b);
|
render_board(b);
|
||||||
|
@@ -80,6 +80,7 @@ enum kb_output {
|
|||||||
KO_NONE,
|
KO_NONE,
|
||||||
KO_INPUT, /* the local input window */
|
KO_INPUT, /* the local input window */
|
||||||
KO_DIALED, /* the 'dialed number' window */
|
KO_DIALED, /* the 'dialed number' window */
|
||||||
|
KO_MESSAGE, /* the 'message' window */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum drag_window { /* which window are we dragging */
|
enum drag_window { /* which window are we dragging */
|
||||||
@@ -91,14 +92,8 @@ enum drag_window { /* which window are we dragging */
|
|||||||
DRAG_MESSAGE, /* message window */
|
DRAG_MESSAGE, /* message window */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct board; /* external. we only need the pointer */
|
|
||||||
|
|
||||||
/*! \brief info related to the gui: button status, mouse coords, etc. */
|
/*! \brief info related to the gui: button status, mouse coords, etc. */
|
||||||
struct gui_info {
|
struct gui_info {
|
||||||
char inbuf[GUI_BUFFER_LEN]; /* buffer for to-dial buffer */
|
|
||||||
int inbuf_pos; /* next free position in inbuf */
|
|
||||||
char msgbuf[GUI_BUFFER_LEN]; /* buffer for text-message buffer */
|
|
||||||
int msgbuf_pos; /* next free position in msgbuf */
|
|
||||||
enum kb_output kb_output; /* where the keyboard output goes */
|
enum kb_output kb_output; /* where the keyboard output goes */
|
||||||
enum drag_window drag_window; /* which window are we dragging */
|
enum drag_window drag_window; /* which window are we dragging */
|
||||||
int x_drag; /* x coordinate where the drag starts */
|
int x_drag; /* x coordinate where the drag starts */
|
||||||
@@ -238,11 +233,12 @@ enum skin_area {
|
|||||||
KEY_SENDVIDEO = 132,
|
KEY_SENDVIDEO = 132,
|
||||||
KEY_LOCALVIDEO = 133,
|
KEY_LOCALVIDEO = 133,
|
||||||
KEY_REMOTEVIDEO = 134,
|
KEY_REMOTEVIDEO = 134,
|
||||||
KEY_WRITEMESSAGE = 135,
|
|
||||||
KEY_FLASH = 136,
|
KEY_FLASH = 136,
|
||||||
KEY_GUI_CLOSE = 199, /* close gui */
|
KEY_GUI_CLOSE = 199, /* close gui */
|
||||||
|
|
||||||
/* regions of the skin - active area, fonts, etc. */
|
/* regions of the skin - displayed area, fonts, etc.
|
||||||
|
* XXX NOTE these are not sensitive areas.
|
||||||
|
*/
|
||||||
KEY_KEYPAD = 200, /* the keypad - default to the whole image */
|
KEY_KEYPAD = 200, /* the keypad - default to the whole image */
|
||||||
KEY_FONT = 201, /* the font. Maybe not really useful */
|
KEY_FONT = 201, /* the font. Maybe not really useful */
|
||||||
KEY_MESSAGE = 202, /* area for incoming messages */
|
KEY_MESSAGE = 202, /* area for incoming messages */
|
||||||
@@ -262,27 +258,6 @@ enum skin_area {
|
|||||||
* Handlers for the various keypad functions
|
* Handlers for the various keypad functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! \brief append a character, or reset if c = '\0' */
|
|
||||||
static void append_char(char *str, int *str_pos, const char c)
|
|
||||||
{
|
|
||||||
int i = *str_pos;
|
|
||||||
if (c == '\0')
|
|
||||||
i = 0;
|
|
||||||
else if (i < GUI_BUFFER_LEN - 1)
|
|
||||||
str[i++] = c;
|
|
||||||
else
|
|
||||||
i = GUI_BUFFER_LEN - 1; /* unnecessary, i think */
|
|
||||||
str = '\0';
|
|
||||||
*str_pos = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! \brief append string to a buffer */
|
|
||||||
static void append_string(char *str, int *str_pos, const char *s)
|
|
||||||
{
|
|
||||||
while (*s)
|
|
||||||
append_char(str, str_pos, *s++);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* accumulate digits, possibly call dial if in connected mode */
|
/* accumulate digits, possibly call dial if in connected mode */
|
||||||
static void keypad_digit(struct video_desc *env, int digit)
|
static void keypad_digit(struct video_desc *env, int digit)
|
||||||
{
|
{
|
||||||
@@ -292,7 +267,9 @@ static void keypad_digit(struct video_desc *env, int digit)
|
|||||||
f.subclass = digit;
|
f.subclass = digit;
|
||||||
ast_queue_frame(env->owner, &f);
|
ast_queue_frame(env->owner, &f);
|
||||||
} else { /* no call, accumulate digits */
|
} else { /* no call, accumulate digits */
|
||||||
append_char(env->gui->inbuf, &env->gui->inbuf_pos, digit);
|
char buf[2] = { digit, '\0' };
|
||||||
|
if (env->gui->bd_msg) /* XXX not strictly necessary ... */
|
||||||
|
print_message(env->gui->bd_msg, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,11 +317,15 @@ static void keypad_pick_up(struct video_desc *env)
|
|||||||
|
|
||||||
if (env->owner) { /* someone is calling us, just answer */
|
if (env->owner) { /* someone is calling us, just answer */
|
||||||
ast_cli_command(gui->outfd, "console answer");
|
ast_cli_command(gui->outfd, "console answer");
|
||||||
} else if (gui->inbuf_pos) { /* we have someone to call */
|
} else { /* we have someone to call */
|
||||||
ast_cli_command(gui->outfd, gui->inbuf);
|
char buf[160];
|
||||||
|
buf[sizeof(buf) - 1] = '\0';
|
||||||
|
snprintf(buf, sizeof(buf) - 1, "console dial %s",
|
||||||
|
ast_skip_blanks(read_message(gui->bd_msg)));
|
||||||
|
ast_log(LOG_WARNING, "doing <%s>\n", buf);
|
||||||
|
reset_board(gui->bd_msg);
|
||||||
|
ast_cli_command(gui->outfd, buf);
|
||||||
}
|
}
|
||||||
append_char(gui->inbuf, &gui->inbuf_pos, '\0'); /* clear buffer */
|
|
||||||
append_string(gui->inbuf, &gui->inbuf_pos, "console dial ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* still unused */
|
#if 0 /* still unused */
|
||||||
@@ -474,30 +455,68 @@ static void handle_mousedown(struct video_desc *env, SDL_MouseButtonEvent button
|
|||||||
* depending on the text_mode variable value.
|
* depending on the text_mode variable value.
|
||||||
*
|
*
|
||||||
* key is the SDLKey structure corresponding to the key pressed.
|
* key is the SDLKey structure corresponding to the key pressed.
|
||||||
* XXX needs to be cleaned up when handling returns etc.
|
* Note that SDL returns modifiers (ctrl, shift, alt) as independent
|
||||||
|
* information so the key itself is not enough and we need to
|
||||||
|
* use a translation table, below - one line per entry,
|
||||||
|
* plain, shift, ctrl, ... using the first char as key.
|
||||||
*/
|
*/
|
||||||
static void handle_keyboard_input(struct video_desc *env, SDLKey key)
|
static const char *us_kbd_map[] = {
|
||||||
|
"`~", "1!", "2@", "3#", "4$", "5%", "6^",
|
||||||
|
"7&", "8*", "9(", "0)", "-_", "=+", "[{",
|
||||||
|
"]}", "\\|", ";:", "'\"", ",<", ".>", "/?",
|
||||||
|
"jJ\n",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char map_key(SDL_keysym *ks)
|
||||||
{
|
{
|
||||||
|
const char *s, **p = us_kbd_map;
|
||||||
|
int c = ks->sym;
|
||||||
|
|
||||||
|
if (c == '\r') /* map cr into lf */
|
||||||
|
c = '\n';
|
||||||
|
if (c >= SDLK_NUMLOCK && c <= SDLK_COMPOSE)
|
||||||
|
return 0; /* only a modifier */
|
||||||
|
if (ks->mod == 0)
|
||||||
|
return c;
|
||||||
|
while ((s = *p) && s[0] != c)
|
||||||
|
p++;
|
||||||
|
if (s) { /* see if we have a modifier and a chance to use it */
|
||||||
|
int l = strlen(s), mod = 0;
|
||||||
|
if (l > 1)
|
||||||
|
mod |= (ks->mod & KMOD_SHIFT) ? 1 : 0;
|
||||||
|
if (l > 2 + mod)
|
||||||
|
mod |= (ks->mod & KMOD_CTRL) ? 2 : 0;
|
||||||
|
if (l > 4 + mod)
|
||||||
|
mod |= (ks->mod & KMOD_ALT) ? 4 : 0;
|
||||||
|
c = s[mod];
|
||||||
|
}
|
||||||
|
if (ks->mod & (KMOD_CAPS|KMOD_SHIFT) && c >= 'a' && c <='z')
|
||||||
|
c += 'A' - 'a';
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_keyboard_input(struct video_desc *env, SDL_keysym *ks)
|
||||||
|
{
|
||||||
|
char buf[2] = { map_key(ks), '\0' };
|
||||||
struct gui_info *gui = env->gui;
|
struct gui_info *gui = env->gui;
|
||||||
|
if (buf[0] == 0) /* modifier ? */
|
||||||
|
return;
|
||||||
switch (gui->kb_output) {
|
switch (gui->kb_output) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
case KO_INPUT:
|
case KO_INPUT: /* to be completed */
|
||||||
/* append in the text-message buffer */
|
break;
|
||||||
if (key == SDLK_RETURN) {
|
case KO_MESSAGE:
|
||||||
/* send the text message and return in normal mode */
|
if (gui->bd_msg) {
|
||||||
gui->kb_output = KO_NONE;
|
print_message(gui->bd_msg, buf);
|
||||||
ast_cli_command(gui->outfd, gui->msgbuf);
|
if (buf[0] == '\r' || buf[0] == '\n') {
|
||||||
append_char(gui->msgbuf, &gui->msgbuf_pos, '\0');
|
keypad_pick_up(env);
|
||||||
} else {
|
}
|
||||||
/* accumulate the key in the message buffer */
|
|
||||||
append_char(gui->msgbuf, &gui->msgbuf_pos, key);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KO_DIALED:
|
|
||||||
/* XXX actually, enter should be a 'console dial ' */
|
case KO_DIALED: /* to be completed */
|
||||||
/* append in the dial buffer */
|
|
||||||
append_char(gui->inbuf, &gui->inbuf_pos, key);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,7 +583,7 @@ static void eventhandler(struct video_desc *env, const char *caption)
|
|||||||
#endif
|
#endif
|
||||||
switch (ev[i].type) {
|
switch (ev[i].type) {
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
handle_keyboard_input(env, ev[i].key.keysym.sym);
|
handle_keyboard_input(env, &ev[i].key.keysym);
|
||||||
break;
|
break;
|
||||||
case SDL_MOUSEMOTION:
|
case SDL_MOUSEMOTION:
|
||||||
if (gui->drag_window == DRAG_LOCAL)
|
if (gui->drag_window == DRAG_LOCAL)
|
||||||
@@ -626,15 +645,10 @@ static struct gui_info *gui_init(const char *keypad_file, const char *font)
|
|||||||
if (gui == NULL)
|
if (gui == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
/* initialize keypad status */
|
/* initialize keypad status */
|
||||||
gui->kb_output = KO_DIALED;
|
gui->kb_output = KO_MESSAGE; /* XXX temp */
|
||||||
gui->drag_window = DRAG_NONE;
|
gui->drag_window = DRAG_NONE;
|
||||||
gui->outfd = -1;
|
gui->outfd = -1;
|
||||||
|
|
||||||
/* initialize keyboard buffer */
|
|
||||||
append_char(gui->inbuf, &gui->inbuf_pos, '\0');
|
|
||||||
append_string(gui->inbuf, &gui->inbuf_pos, "console dial ");
|
|
||||||
append_char(gui->msgbuf, &gui->msgbuf_pos, '\0');
|
|
||||||
|
|
||||||
keypad_setup(gui, keypad_file);
|
keypad_setup(gui, keypad_file);
|
||||||
if (gui->keypad == NULL) /* no keypad, we are done */
|
if (gui->keypad == NULL) /* no keypad, we are done */
|
||||||
return gui;
|
return gui;
|
||||||
@@ -896,7 +910,6 @@ static struct _s_k gui_key_map[] = {
|
|||||||
{"SENDVIDEO", KEY_SENDVIDEO },
|
{"SENDVIDEO", KEY_SENDVIDEO },
|
||||||
{"LOCALVIDEO", KEY_LOCALVIDEO },
|
{"LOCALVIDEO", KEY_LOCALVIDEO },
|
||||||
{"REMOTEVIDEO", KEY_REMOTEVIDEO },
|
{"REMOTEVIDEO", KEY_REMOTEVIDEO },
|
||||||
{"WRITEMESSAGE", KEY_WRITEMESSAGE },
|
|
||||||
{"GUI_CLOSE", KEY_GUI_CLOSE },
|
{"GUI_CLOSE", KEY_GUI_CLOSE },
|
||||||
{"KEYPAD", KEY_KEYPAD }, /* x0 y0 w h - active area of the keypad */
|
{"KEYPAD", KEY_KEYPAD }, /* x0 y0 w h - active area of the keypad */
|
||||||
{"MESSAGE", KEY_MESSAGE }, /* x0 y0 w h - incoming messages */
|
{"MESSAGE", KEY_MESSAGE }, /* x0 y0 w h - incoming messages */
|
||||||
|
@@ -667,8 +667,6 @@ static struct ast_frame *get_video_frames(struct video_desc *env, struct ast_fra
|
|||||||
return v->enc->enc_encap(&v->enc_out, v->mtu, tail);
|
return v->enc->enc_encap(&v->enc_out, v->mtu, tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_message(struct board *b, const char *s);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper thread to periodically poll the video source and enqueue the
|
* Helper thread to periodically poll the video source and enqueue the
|
||||||
* generated frames to the channel's queue.
|
* generated frames to the channel's queue.
|
||||||
@@ -725,10 +723,6 @@ static void *video_thread(void *arg)
|
|||||||
int fd;
|
int fd;
|
||||||
char *caption = NULL, buf[160];
|
char *caption = NULL, buf[160];
|
||||||
|
|
||||||
sprintf(buf, "%d \r", count);
|
|
||||||
if (env->gui)
|
|
||||||
print_message(env->gui->bd_msg, buf);
|
|
||||||
|
|
||||||
/* determine if video format changed */
|
/* determine if video format changed */
|
||||||
if (count++ % 10 == 0) {
|
if (count++ % 10 == 0) {
|
||||||
if (env->out.sendvideo)
|
if (env->out.sendvideo)
|
||||||
|
@@ -86,5 +86,16 @@ int console_video_config(struct video_desc **penv, const char *var, const char *
|
|||||||
void console_video_uninit(struct video_desc *env);
|
void console_video_uninit(struct video_desc *env);
|
||||||
void console_video_start(struct video_desc *env, struct ast_channel *owner);
|
void console_video_start(struct video_desc *env, struct ast_channel *owner);
|
||||||
|
|
||||||
|
/* console_board.c */
|
||||||
|
struct board;
|
||||||
|
/* !\brief print a message on a board */
|
||||||
|
int print_message(struct board *b, const char *s);
|
||||||
|
|
||||||
|
/*! \brief return the whole text from a board */
|
||||||
|
const char *read_message(const struct board *b);
|
||||||
|
|
||||||
|
/*! \brief reset the board to blank */
|
||||||
|
int reset_board(struct board *b);
|
||||||
|
|
||||||
#endif /* CONSOLE_VIDEO_H */
|
#endif /* CONSOLE_VIDEO_H */
|
||||||
/* end of file */
|
/* end of file */
|
||||||
|
Reference in New Issue
Block a user