From 1e7077c8bda1eab42913c7d8050d29e65f3f2044 Mon Sep 17 00:00:00 2001 From: rizzo Date: Wed, 9 Jan 2008 16:44:20 +0000 Subject: 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: http://svn.digium.com/svn/asterisk/trunk@97488 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/console_board.c | 23 +++++++-- channels/console_gui.c | 129 ++++++++++++++++++++++++++--------------------- channels/console_video.c | 6 --- channels/console_video.h | 11 ++++ 4 files changed, 102 insertions(+), 67 deletions(-) (limited to 'channels') diff --git a/channels/console_board.c b/channels/console_board.c index 9096a8516..9c913f8a3 100644 --- a/channels/console_board.c +++ b/channels/console_board.c @@ -39,6 +39,7 @@ #include "asterisk.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 */ #include @@ -180,8 +181,8 @@ static void render_board(struct board *b) /* blit all characters */ for (i = first_char, col = 0; i < last_char; i++) { int c = b->text[i] - 32; /* XXX first 32 chars are not printable */ - if (c < 0) /* should not happen, but just in case... */ - continue; + if (c < 0) /* buffer terminator or anything else is a blank */ + c = 0; SDL_BlitSurface(b->font, &b->font_rects[c], b->screen, &dst); /* point dst to next char position */ 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 */ } +/* 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 * and blit on screen if required. * 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 i, l, row, col; @@ -261,12 +275,14 @@ int print_message(struct board *b, const char *s) col = 0; break; case '\n': /* move to beginning of next line */ + dst[col] = '\0'; /* mark the rest of the line as empty */ col = 0; dst += b->v_w; break; case '\b': /* one char back */ if (col > 0) col--; + dst[col] = ' '; /* delete current char */ break; default: if (s[i] < 32) /* signed, so take up to 127 */ @@ -280,6 +296,7 @@ int print_message(struct board *b, const char *s) break; } } + dst[col] = '\0'; /* the current position is empty */ b->cur_col = col; /* everything is printed now, must do the rendering */ render_board(b); diff --git a/channels/console_gui.c b/channels/console_gui.c index 7b4cf23ce..2bdbdf69c 100644 --- a/channels/console_gui.c +++ b/channels/console_gui.c @@ -80,6 +80,7 @@ enum kb_output { KO_NONE, KO_INPUT, /* the local input window */ KO_DIALED, /* the 'dialed number' window */ + KO_MESSAGE, /* the 'message' window */ }; enum drag_window { /* which window are we dragging */ @@ -91,14 +92,8 @@ enum drag_window { /* which window are we dragging */ DRAG_MESSAGE, /* message window */ }; -struct board; /* external. we only need the pointer */ - /*! \brief info related to the gui: button status, mouse coords, etc. */ 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 drag_window drag_window; /* which window are we dragging */ int x_drag; /* x coordinate where the drag starts */ @@ -238,11 +233,12 @@ enum skin_area { KEY_SENDVIDEO = 132, KEY_LOCALVIDEO = 133, KEY_REMOTEVIDEO = 134, - KEY_WRITEMESSAGE = 135, KEY_FLASH = 136, 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_FONT = 201, /* the font. Maybe not really useful */ KEY_MESSAGE = 202, /* area for incoming messages */ @@ -262,27 +258,6 @@ enum skin_area { * 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 */ 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; ast_queue_frame(env->owner, &f); } 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 */ ast_cli_command(gui->outfd, "console answer"); - } else if (gui->inbuf_pos) { /* we have someone to call */ - ast_cli_command(gui->outfd, gui->inbuf); + } else { /* we have someone to call */ + 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 */ @@ -474,30 +455,68 @@ static void handle_mousedown(struct video_desc *env, SDL_MouseButtonEvent button * depending on the text_mode variable value. * * 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; + if (buf[0] == 0) /* modifier ? */ + return; switch (gui->kb_output) { default: break; - case KO_INPUT: - /* append in the text-message buffer */ - if (key == SDLK_RETURN) { - /* send the text message and return in normal mode */ - gui->kb_output = KO_NONE; - ast_cli_command(gui->outfd, gui->msgbuf); - append_char(gui->msgbuf, &gui->msgbuf_pos, '\0'); - } else { - /* accumulate the key in the message buffer */ - append_char(gui->msgbuf, &gui->msgbuf_pos, key); + case KO_INPUT: /* to be completed */ + break; + case KO_MESSAGE: + if (gui->bd_msg) { + print_message(gui->bd_msg, buf); + if (buf[0] == '\r' || buf[0] == '\n') { + keypad_pick_up(env); + } } break; - case KO_DIALED: - /* XXX actually, enter should be a 'console dial ' */ - /* append in the dial buffer */ - append_char(gui->inbuf, &gui->inbuf_pos, key); + + case KO_DIALED: /* to be completed */ break; } @@ -564,7 +583,7 @@ static void eventhandler(struct video_desc *env, const char *caption) #endif switch (ev[i].type) { case SDL_KEYDOWN: - handle_keyboard_input(env, ev[i].key.keysym.sym); + handle_keyboard_input(env, &ev[i].key.keysym); break; case SDL_MOUSEMOTION: 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) return NULL; /* initialize keypad status */ - gui->kb_output = KO_DIALED; + gui->kb_output = KO_MESSAGE; /* XXX temp */ gui->drag_window = DRAG_NONE; 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); if (gui->keypad == NULL) /* no keypad, we are done */ return gui; @@ -896,7 +910,6 @@ static struct _s_k gui_key_map[] = { {"SENDVIDEO", KEY_SENDVIDEO }, {"LOCALVIDEO", KEY_LOCALVIDEO }, {"REMOTEVIDEO", KEY_REMOTEVIDEO }, - {"WRITEMESSAGE", KEY_WRITEMESSAGE }, {"GUI_CLOSE", KEY_GUI_CLOSE }, {"KEYPAD", KEY_KEYPAD }, /* x0 y0 w h - active area of the keypad */ {"MESSAGE", KEY_MESSAGE }, /* x0 y0 w h - incoming messages */ diff --git a/channels/console_video.c b/channels/console_video.c index 4cc0809d3..5c7e87e72 100644 --- a/channels/console_video.c +++ b/channels/console_video.c @@ -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); } -int print_message(struct board *b, const char *s); - /* * Helper thread to periodically poll the video source and enqueue the * generated frames to the channel's queue. @@ -725,10 +723,6 @@ static void *video_thread(void *arg) int fd; 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 */ if (count++ % 10 == 0) { if (env->out.sendvideo) diff --git a/channels/console_video.h b/channels/console_video.h index 3d3975a67..8314da3a8 100644 --- a/channels/console_video.h +++ b/channels/console_video.h @@ -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_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 */ /* end of file */ -- cgit v1.2.3