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
00034
00035
00036
00037
00038 #include "asterisk.h"
00039 #include "console_video.h"
00040 #include "asterisk/lock.h"
00041 #include "asterisk/frame.h"
00042 #include "asterisk/utils.h"
00043 #include <math.h>
00044
00045
00046 enum { WIN_LOCAL, WIN_REMOTE, WIN_KEYPAD, WIN_MAX };
00047
00048 #ifndef HAVE_SDL
00049 static void show_frame(struct video_desc *env, int out) {}
00050 static void sdl_setup(struct video_desc *env) {}
00051 static struct gui_info *cleanup_sdl(struct gui_info *gui) { return NULL; }
00052 static void eventhandler(struct video_desc *env, const char *caption) {}
00053 static int keypad_cfg_read(struct gui_info *gui, const char *val) { return 0; }
00054
00055 #else
00056
00057 #include <SDL/SDL.h>
00058 #ifdef HAVE_SDL_IMAGE
00059 #include <SDL/SDL_image.h>
00060 #endif
00061
00062 enum kp_type { KP_NONE, KP_RECT, KP_CIRCLE };
00063 struct keypad_entry {
00064 int c;
00065 int x0, y0, x1, y1, h;
00066 enum kp_type type;
00067 };
00068
00069
00070
00071
00072 struct display_window {
00073 SDL_Overlay *bmp;
00074 SDL_Rect rect;
00075 };
00076
00077 struct gui_info {
00078 enum kb_output kb_output;
00079 struct drag_info drag;
00080
00081 SDL_Surface *screen;
00082
00083 int outfd;
00084 SDL_Surface *keypad;
00085 SDL_Rect kp_rect;
00086 SDL_Surface *font;
00087 SDL_Rect font_rects[96];
00088
00089
00090
00091
00092
00093 SDL_Rect kp_msg[2];
00094 struct board *bd_msg;
00095
00096 SDL_Rect kp_edit[2];
00097 struct board *bd_edit;
00098
00099 SDL_Rect kp_dialed[2];
00100 struct board *bd_dialed;
00101
00102
00103 int kp_size, kp_used;
00104 struct keypad_entry *kp;
00105
00106 struct display_window win[WIN_MAX];
00107 };
00108
00109
00110
00111
00112 static struct gui_info *cleanup_sdl(struct gui_info *gui)
00113 {
00114 int i;
00115
00116 if (gui == NULL)
00117 return NULL;
00118
00119
00120 if (gui->font) {
00121 SDL_FreeSurface(gui->font);
00122 gui->font = NULL;
00123 }
00124
00125 if (gui->outfd > -1)
00126 close(gui->outfd);
00127 if (gui->keypad)
00128 SDL_FreeSurface(gui->keypad);
00129 gui->keypad = NULL;
00130 if (gui->kp)
00131 ast_free(gui->kp);
00132
00133
00134 for (i = 0; i < WIN_MAX; i++) {
00135 if (gui->win[i].bmp)
00136 SDL_FreeYUVOverlay(gui->win[i].bmp);
00137 }
00138 memset(gui, '\0', sizeof(gui));
00139 ast_free(gui);
00140 SDL_Quit();
00141 return NULL;
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static void show_frame(struct video_desc *env, int out)
00155 {
00156 AVPicture *p_in, p_out;
00157 struct fbuf_t *b_in, *b_out;
00158 SDL_Overlay *bmp;
00159 struct gui_info *gui = env->gui;
00160
00161 if (!gui)
00162 return;
00163
00164 if (out == WIN_LOCAL) {
00165 b_in = &env->enc_in;
00166 b_out = &env->loc_dpy;
00167 p_in = NULL;
00168 } else {
00169
00170 AVCodecContext *c;
00171 if (env->in == NULL)
00172 return;
00173 c = env->in->dec_ctx;
00174 b_in = &env->in->dec_out;
00175 b_in->pix_fmt = c->pix_fmt;
00176 b_in->w = c->width;
00177 b_in->h = c->height;
00178
00179 b_out = &env->rem_dpy;
00180 p_in = (AVPicture *)env->in->d_frame;
00181 }
00182 bmp = gui->win[out].bmp;
00183 SDL_LockYUVOverlay(bmp);
00184
00185 memset(&p_out, '\0', sizeof(p_out));
00186 p_out.data[0] = bmp->pixels[0];
00187 p_out.data[1] = bmp->pixels[1];
00188 p_out.data[2] = bmp->pixels[2];
00189 p_out.linesize[0] = bmp->pitches[0];
00190 p_out.linesize[1] = bmp->pitches[1];
00191 p_out.linesize[2] = bmp->pitches[2];
00192
00193 my_scale(b_in, p_in, b_out, &p_out);
00194
00195
00196 SDL_DisplayYUVOverlay(bmp, &gui->win[out].rect);
00197 SDL_UnlockYUVOverlay(bmp);
00198 }
00199
00200
00201
00202
00203
00204
00205
00206 enum skin_area {
00207
00208 KEY_PICK_UP = 128,
00209 KEY_HANG_UP = 129,
00210
00211 KEY_MUTE = 130,
00212 KEY_AUTOANSWER = 131,
00213 KEY_SENDVIDEO = 132,
00214 KEY_LOCALVIDEO = 133,
00215 KEY_REMOTEVIDEO = 134,
00216 KEY_FLASH = 136,
00217
00218
00219 KEY_MESSAGEBOARD = 140,
00220 KEY_DIALEDBOARD = 141,
00221 KEY_EDITBOARD = 142,
00222
00223 KEY_GUI_CLOSE = 199,
00224
00225
00226
00227 KEY_KEYPAD = 200,
00228 KEY_FONT = 201,
00229 KEY_MESSAGE = 202,
00230 KEY_DIALED = 203,
00231 KEY_EDIT = 204,
00232
00233
00234 KEY_OUT_OF_KEYPAD = 241,
00235 KEY_REM_DPY = 242,
00236 KEY_LOC_DPY = 243,
00237 KEY_RESET = 253,
00238 KEY_NONE = 254,
00239 KEY_DIGIT_BACKGROUND = 255,
00240 };
00241
00242
00243
00244
00245
00246
00247 static void keypad_digit(struct video_desc *env, int digit)
00248 {
00249 if (env->owner) {
00250 struct ast_frame f = { AST_FRAME_DTMF, 0 };
00251
00252 f.subclass = digit;
00253 ast_queue_frame(env->owner, &f);
00254 } else {
00255 char buf[2] = { digit, '\0' };
00256 if (env->gui->bd_msg)
00257 print_message(env->gui->bd_msg, buf);
00258 }
00259 }
00260
00261
00262 static char *keypad_toggle(struct video_desc *env, int index)
00263 {
00264 ast_log(LOG_WARNING, "keypad_toggle(%i) called\n", index);
00265
00266 switch (index) {
00267 case KEY_SENDVIDEO:
00268 env->out.sendvideo = !env->out.sendvideo;
00269 break;
00270 #ifdef notyet
00271 case KEY_MUTE: {
00272 struct chan_oss_pvt *o = find_desc(oss_active);
00273 o->mute = !o->mute;
00274 }
00275 break;
00276 case KEY_AUTOANSWER: {
00277 struct chan_oss_pvt *o = find_desc(oss_active);
00278 o->autoanswer = !o->autoanswer;
00279 }
00280 break;
00281 #endif
00282 }
00283 return NULL;
00284 }
00285
00286 char *console_do_answer(int fd);
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 static void keypad_pick_up(struct video_desc *env)
00298 {
00299 struct gui_info *gui = env->gui;
00300
00301 ast_log(LOG_WARNING, "keypad_pick_up called\n");
00302
00303 if (env->owner) {
00304 ast_cli_command(gui->outfd, "console answer");
00305 } else {
00306 char buf[160];
00307 const char *who = ast_skip_blanks(read_message(gui->bd_msg));
00308 buf[sizeof(buf) - 1] = '\0';
00309 snprintf(buf, sizeof(buf), "console dial %s", who);
00310 ast_log(LOG_WARNING, "doing <%s>\n", buf);
00311 print_message(gui->bd_dialed, "\n");
00312 print_message(gui->bd_dialed, who);
00313 reset_board(gui->bd_msg);
00314 ast_cli_command(gui->outfd, buf);
00315 }
00316 }
00317
00318 #if 0
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 static int gui_output(struct video_desc *env, const char *text)
00338 {
00339 return 1;
00340 }
00341 #endif
00342
00343 static int video_geom(struct fbuf_t *b, const char *s);
00344 static void sdl_setup(struct video_desc *env);
00345 static int kp_match_area(const struct keypad_entry *e, int x, int y);
00346
00347 static void set_drag(struct drag_info *drag, int x, int y, enum drag_window win)
00348 {
00349 drag->x_start = x;
00350 drag->y_start = y;
00351 drag->drag_window = win;
00352 }
00353
00354
00355
00356
00357
00358
00359
00360 static void handle_mousedown(struct video_desc *env, SDL_MouseButtonEvent button)
00361 {
00362 uint8_t index = KEY_OUT_OF_KEYPAD;
00363 struct gui_info *gui = env->gui;
00364
00365 #if 0
00366 ast_log(LOG_WARNING, "event %d %d have %d/%d regions at %p\n",
00367 button.x, button.y, gui->kp_used, gui->kp_size, gui->kp);
00368 #endif
00369
00370 gui->drag.drag_window = DRAG_NONE;
00371
00372
00373 if (button.x < env->rem_dpy.w)
00374 index = KEY_REM_DPY;
00375 else if (button.x > env->rem_dpy.w + gui->keypad->w)
00376 index = KEY_LOC_DPY;
00377 else if (button.y > gui->keypad->h)
00378 index = KEY_OUT_OF_KEYPAD;
00379 else if (gui->kp) {
00380 int i;
00381 for (i = 0; i < gui->kp_used; i++) {
00382 if (kp_match_area(&gui->kp[i], button.x - env->rem_dpy.w, button.y)) {
00383 index = gui->kp[i].c;
00384 break;
00385 }
00386 }
00387 }
00388
00389
00390 if (index < 128) {
00391 keypad_digit(env, index);
00392 return;
00393 }
00394 switch (index) {
00395
00396 case KEY_PICK_UP:
00397 keypad_pick_up(env);
00398 break;
00399 case KEY_HANG_UP:
00400 ast_cli_command(gui->outfd, "console hangup");
00401 break;
00402
00403
00404 case KEY_MUTE:
00405 case KEY_AUTOANSWER:
00406 case KEY_SENDVIDEO:
00407 keypad_toggle(env, index);
00408 break;
00409
00410 case KEY_LOCALVIDEO:
00411 break;
00412 case KEY_REMOTEVIDEO:
00413 break;
00414
00415 case KEY_MESSAGEBOARD:
00416 if (button.button == SDL_BUTTON_LEFT)
00417 set_drag(&gui->drag, button.x, button.y, DRAG_MESSAGE);
00418 break;
00419
00420
00421 case KEY_LOC_DPY:
00422 case KEY_REM_DPY:
00423 if (button.button == SDL_BUTTON_LEFT) {
00424 if (index == KEY_LOC_DPY)
00425 set_drag(&gui->drag, button.x, button.y, DRAG_LOCAL);
00426 break;
00427 } else {
00428 char buf[128];
00429 struct fbuf_t *fb = index == KEY_LOC_DPY ? &env->loc_dpy : &env->rem_dpy;
00430 sprintf(buf, "%c%dx%d", button.button == SDL_BUTTON_RIGHT ? '>' : '<',
00431 fb->w, fb->h);
00432 video_geom(fb, buf);
00433 sdl_setup(env);
00434 }
00435 break;
00436 case KEY_OUT_OF_KEYPAD:
00437 break;
00438
00439 case KEY_DIGIT_BACKGROUND:
00440 break;
00441 default:
00442 ast_log(LOG_WARNING, "function not yet defined %i\n", index);
00443 }
00444 }
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 static const char *us_kbd_map[] = {
00458 "`~", "1!", "2@", "3#", "4$", "5%", "6^",
00459 "7&", "8*", "9(", "0)", "-_", "=+", "[{",
00460 "]}", "\\|", ";:", "'\"", ",<", ".>", "/?",
00461 "jJ\n",
00462 NULL
00463 };
00464
00465 static char map_key(SDL_keysym *ks)
00466 {
00467 const char *s, **p = us_kbd_map;
00468 int c = ks->sym;
00469
00470 if (c == '\r')
00471 c = '\n';
00472 if (c >= SDLK_NUMLOCK && c <= SDLK_COMPOSE)
00473 return 0;
00474 if (ks->mod == 0)
00475 return c;
00476 while ((s = *p) && s[0] != c)
00477 p++;
00478 if (s) {
00479 int l = strlen(s), mod = 0;
00480 if (l > 1)
00481 mod |= (ks->mod & KMOD_SHIFT) ? 1 : 0;
00482 if (l > 2 + mod)
00483 mod |= (ks->mod & KMOD_CTRL) ? 2 : 0;
00484 if (l > 4 + mod)
00485 mod |= (ks->mod & KMOD_ALT) ? 4 : 0;
00486 c = s[mod];
00487 }
00488 if (ks->mod & (KMOD_CAPS|KMOD_SHIFT) && c >= 'a' && c <='z')
00489 c += 'A' - 'a';
00490 return c;
00491 }
00492
00493 static void handle_keyboard_input(struct video_desc *env, SDL_keysym *ks)
00494 {
00495 char buf[2] = { map_key(ks), '\0' };
00496 struct gui_info *gui = env->gui;
00497 if (buf[0] == 0)
00498 return;
00499 switch (gui->kb_output) {
00500 default:
00501 break;
00502 case KO_INPUT:
00503 break;
00504 case KO_MESSAGE:
00505 if (gui->bd_msg) {
00506 print_message(gui->bd_msg, buf);
00507 if (buf[0] == '\r' || buf[0] == '\n') {
00508 keypad_pick_up(env);
00509 }
00510 }
00511 break;
00512
00513 case KO_DIALED:
00514 break;
00515 }
00516
00517 return;
00518 }
00519
00520 static void grabber_move(struct video_out_desc *, int dx, int dy);
00521
00522 int compute_drag(int *start, int end, int magnifier);
00523 int compute_drag(int *start, int end, int magnifier)
00524 {
00525 int delta = end - *start;
00526 #define POLARITY -1
00527
00528 delta += delta * delta * (delta > 0 ? 1 : -1 )/100;
00529 delta *= POLARITY * magnifier;
00530 #undef POLARITY
00531 *start = end;
00532 return delta;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 static void eventhandler(struct video_desc *env, const char *caption)
00545 {
00546 struct gui_info *gui = env->gui;
00547 struct drag_info *drag;
00548 #define N_EVENTS 32
00549 int i, n;
00550 SDL_Event ev[N_EVENTS];
00551
00552 if (!gui)
00553 return;
00554 drag = &gui->drag;
00555 if (caption)
00556 SDL_WM_SetCaption(caption, NULL);
00557
00558 #define MY_EV (SDL_MOUSEBUTTONDOWN|SDL_KEYDOWN)
00559 while ( (n = SDL_PeepEvents(ev, N_EVENTS, SDL_GETEVENT, SDL_ALLEVENTS)) > 0) {
00560 for (i = 0; i < n; i++) {
00561 #if 0
00562 ast_log(LOG_WARNING, "------ event %d at %d %d\n",
00563 ev[i].type, ev[i].button.x, ev[i].button.y);
00564 #endif
00565 switch (ev[i].type) {
00566 case SDL_KEYDOWN:
00567 handle_keyboard_input(env, &ev[i].key.keysym);
00568 break;
00569 case SDL_MOUSEMOTION:
00570 case SDL_MOUSEBUTTONUP:
00571 if (drag->drag_window == DRAG_LOCAL) {
00572
00573 int dx = compute_drag(&drag->x_start, ev[i].motion.x, 3);
00574 int dy = compute_drag(&drag->y_start, ev[i].motion.y, 3);
00575 grabber_move(&env->out, dx, dy);
00576 } else if (drag->drag_window == DRAG_MESSAGE) {
00577
00578 int dy = compute_drag(&drag->y_start, ev[i].motion.y, 1);
00579 move_message_board(gui->bd_msg, dy);
00580 }
00581 if (ev[i].type == SDL_MOUSEBUTTONUP)
00582 drag->drag_window = DRAG_NONE;
00583 break;
00584 case SDL_MOUSEBUTTONDOWN:
00585 handle_mousedown(env, ev[i].button);
00586 break;
00587 }
00588 }
00589 }
00590 if (1) {
00591 struct timeval b, a = ast_tvnow();
00592 int i;
00593
00594 SDL_PumpEvents();
00595 b = ast_tvnow();
00596 i = ast_tvdiff_ms(b, a);
00597 if (i > 3)
00598 fprintf(stderr, "-------- SDL_PumpEvents took %dms\n", i);
00599
00600 }
00601 }
00602
00603 static SDL_Surface *load_image(const char *file)
00604 {
00605 SDL_Surface *temp;
00606
00607 #ifdef HAVE_SDL_IMAGE
00608 temp = IMG_Load(file);
00609 #else
00610 temp = SDL_LoadBMP(file);
00611 #endif
00612 if (temp == NULL)
00613 fprintf(stderr, "Unable to load image %s: %s\n",
00614 file, SDL_GetError());
00615 return temp;
00616 }
00617
00618 static void keypad_setup(struct gui_info *gui, const char *kp_file);
00619
00620
00621
00622 static struct gui_info *gui_init(const char *keypad_file, const char *font)
00623 {
00624 struct gui_info *gui = ast_calloc(1, sizeof(*gui));
00625
00626 if (gui == NULL)
00627 return NULL;
00628
00629 gui->kb_output = KO_MESSAGE;
00630 gui->drag.drag_window = DRAG_NONE;
00631 gui->outfd = -1;
00632
00633 keypad_setup(gui, keypad_file);
00634 if (gui->keypad == NULL)
00635 return gui;
00636
00637 if (!ast_strlen_zero(font)) {
00638 int i;
00639 SDL_Rect *r;
00640
00641 gui->font = load_image(font);
00642 if (!gui->font) {
00643 ast_log(LOG_WARNING, "Unable to load font %s, no output available\n", font);
00644 goto error;
00645 }
00646 ast_log(LOG_WARNING, "Loaded font %s\n", font);
00647
00648 r = gui->font_rects;
00649 #define FONT_H 20
00650 #define FONT_W 9
00651 for (i = 0; i < 96; r++, i++) {
00652 r->x = (i % 32 ) * FONT_W;
00653 r->y = (i / 32 ) * FONT_H;
00654 r->w = FONT_W;
00655 r->h = FONT_H;
00656 }
00657 }
00658
00659 gui->outfd = open ("/dev/null", O_WRONLY);
00660 if (gui->outfd < 0) {
00661 ast_log(LOG_WARNING, "Unable output fd\n");
00662 goto error;
00663 }
00664 return gui;
00665
00666 error:
00667 ast_free(gui);
00668 return NULL;
00669 }
00670
00671
00672 static int set_win(SDL_Surface *screen, struct display_window *win, int fmt,
00673 int w, int h, int x, int y)
00674 {
00675 win->bmp = SDL_CreateYUVOverlay(w, h, fmt, screen);
00676 if (win->bmp == NULL)
00677 return -1;
00678 win->rect.x = x;
00679 win->rect.y = y;
00680 win->rect.w = w;
00681 win->rect.h = h;
00682 return 0;
00683 }
00684
00685 static int keypad_cfg_read(struct gui_info *gui, const char *val);
00686
00687 static void keypad_setup(struct gui_info *gui, const char *kp_file)
00688 {
00689 FILE *fd;
00690 char buf[1024];
00691 const char region[] = "region";
00692 int reg_len = strlen(region);
00693 int in_comment = 0;
00694
00695 if (gui->keypad)
00696 return;
00697 gui->keypad = load_image(kp_file);
00698 if (!gui->keypad)
00699 return;
00700
00701 fd = fopen(kp_file, "r");
00702 if (fd == NULL) {
00703 ast_log(LOG_WARNING, "fail to open %s\n", kp_file);
00704 return;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 while (fgets(buf, sizeof(buf), fd)) {
00716 char *s;
00717
00718 if (!strstr(buf, region)) {
00719 if (!in_comment)
00720 continue;
00721 else
00722 break;
00723 }
00724 if (!in_comment) {
00725 keypad_cfg_read(gui, "reset");
00726 in_comment = 1;
00727 }
00728 s = ast_skip_blanks(buf);
00729 ast_trim_blanks(s);
00730 if (memcmp(s, region, reg_len))
00731 break;
00732 s = ast_skip_blanks(s + reg_len);
00733 if (*s++ != '=')
00734 break;
00735 if (*s == '>')
00736 s++;
00737 keypad_cfg_read(gui, ast_skip_blanks(s));
00738 }
00739 fclose(fd);
00740 }
00741
00742 struct board *board_setup(SDL_Surface *screen, SDL_Rect *dest,
00743 SDL_Surface *font, SDL_Rect *font_rects);
00744
00745
00746 static void init_board(struct gui_info *gui, struct board **dst, SDL_Rect *r, int dx, int dy)
00747 {
00748 if (r[0].w == 0 || r[0].h == 0)
00749 return;
00750 r[1] = r[0];
00751 r[1].x += dx;
00752 r[1].y += dy;
00753 if (*dst == NULL) {
00754 *dst = board_setup(gui->screen, &r[1], gui->font, gui->font_rects);
00755 } else {
00756
00757 }
00758 }
00759
00760
00761
00762
00763
00764 static void sdl_setup(struct video_desc *env)
00765 {
00766 int dpy_fmt = SDL_IYUV_OVERLAY;
00767 int depth, maxw, maxh;
00768 const SDL_VideoInfo *info;
00769 int kp_w = 0, kp_h = 0;
00770 struct gui_info *gui = env->gui;
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 if (gui == NULL && SDL_Init(SDL_INIT_VIDEO)) {
00784 ast_log(LOG_WARNING, "Could not initialize SDL - %s\n",
00785 SDL_GetError());
00786
00787 return;
00788 }
00789 info = SDL_GetVideoInfo();
00790
00791
00792
00793 depth = info->vfmt->BitsPerPixel;
00794 if (depth < 16)
00795 depth = 16;
00796 if (!gui)
00797 env->gui = gui = gui_init(env->keypad_file, env->keypad_font);
00798 if (!gui)
00799 goto no_sdl;
00800
00801 if (gui->keypad) {
00802 if (gui->kp_rect.w > 0 && gui->kp_rect.h > 0) {
00803 kp_w = gui->kp_rect.w;
00804 kp_h = gui->kp_rect.h;
00805 } else {
00806 kp_w = gui->keypad->w;
00807 kp_h = gui->keypad->h;
00808 }
00809 }
00810
00811 #define BORDER 5
00812 maxw = env->rem_dpy.w + env->loc_dpy.w + kp_w;
00813 maxh = MAX( MAX(env->rem_dpy.h, env->loc_dpy.h), kp_h);
00814 maxw += 4 * BORDER;
00815 maxh += 2 * BORDER;
00816 gui->screen = SDL_SetVideoMode(maxw, maxh, depth, 0);
00817 if (!gui->screen) {
00818 ast_log(LOG_ERROR, "SDL: could not set video mode - exiting\n");
00819 goto no_sdl;
00820 }
00821
00822 SDL_WM_SetCaption("Asterisk console Video Output", NULL);
00823 if (set_win(gui->screen, &gui->win[WIN_REMOTE], dpy_fmt,
00824 env->rem_dpy.w, env->rem_dpy.h, BORDER, BORDER))
00825 goto no_sdl;
00826 if (set_win(gui->screen, &gui->win[WIN_LOCAL], dpy_fmt,
00827 env->loc_dpy.w, env->loc_dpy.h,
00828 3*BORDER+env->rem_dpy.w + kp_w, BORDER))
00829 goto no_sdl;
00830
00831
00832
00833
00834 if (gui->keypad) {
00835 struct SDL_Rect *dest = &gui->win[WIN_KEYPAD].rect;
00836 struct SDL_Rect *src = (gui->kp_rect.w > 0 && gui->kp_rect.h > 0) ? & gui->kp_rect : NULL;
00837
00838 dest->x = 2*BORDER + env->rem_dpy.w;
00839 dest->y = BORDER;
00840 dest->w = kp_w;
00841 dest->h = kp_h;
00842 SDL_BlitSurface(gui->keypad, src, gui->screen, dest);
00843 init_board(gui, &gui->bd_msg, gui->kp_msg, dest->x, dest->y);
00844 init_board(gui, &gui->bd_dialed, gui->kp_dialed, dest->x, dest->y);
00845 SDL_UpdateRects(gui->screen, 1, dest);
00846 }
00847 return;
00848
00849 no_sdl:
00850
00851 env->gui = cleanup_sdl(gui);
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 static int kp_match_area(const struct keypad_entry *e, int x, int y)
00866 {
00867 double xp, dx = (e->x1 - e->x0);
00868 double yp, dy = (e->y1 - e->y0);
00869 double l = sqrt(dx*dx + dy*dy);
00870 int ret = 0;
00871
00872 if (l > 1) {
00873 xp = ((x - e->x0)*dx + (y - e->y0)*dy)/l;
00874 yp = (-(x - e->x0)*dy + (y - e->y0)*dx)/l;
00875 if (e->type == KP_RECT) {
00876 ret = (xp >= 0 && xp < l && yp >=0 && yp < l);
00877 } else if (e->type == KP_CIRCLE) {
00878 dx = xp*xp/(l*l) + yp*yp/(e->h*e->h);
00879 ret = (dx < 1);
00880 }
00881 }
00882 #if 0
00883 ast_log(LOG_WARNING, "result %d [%d] for match %d,%d in type %d p0 %d,%d p1 %d,%d h %d\n",
00884 ret, e->c, x, y, e->type, e->x0, e->y0, e->x1, e->y1, e->h);
00885 #endif
00886 return ret;
00887 }
00888
00889 struct _s_k { const char *s; int k; };
00890 static struct _s_k gui_key_map[] = {
00891 {"PICK_UP", KEY_PICK_UP },
00892 {"PICKUP", KEY_PICK_UP },
00893 {"HANG_UP", KEY_HANG_UP },
00894 {"HANGUP", KEY_HANG_UP },
00895 {"MUTE", KEY_MUTE },
00896 {"FLASH", KEY_FLASH },
00897 {"AUTOANSWER", KEY_AUTOANSWER },
00898 {"SENDVIDEO", KEY_SENDVIDEO },
00899 {"LOCALVIDEO", KEY_LOCALVIDEO },
00900 {"REMOTEVIDEO", KEY_REMOTEVIDEO },
00901 {"GUI_CLOSE", KEY_GUI_CLOSE },
00902 {"MESSAGEBOARD", KEY_MESSAGEBOARD },
00903 {"DIALEDBOARD", KEY_DIALEDBOARD },
00904 {"EDITBOARD", KEY_EDITBOARD },
00905 {"KEYPAD", KEY_KEYPAD },
00906 {"MESSAGE", KEY_MESSAGE },
00907 {"DIALED", KEY_DIALED },
00908 {"EDIT", KEY_EDIT },
00909 {"FONT", KEY_FONT },
00910 {NULL, 0 } };
00911
00912 static int gui_map_token(const char *s)
00913 {
00914
00915 int i = atoi(s);
00916 struct _s_k *p;
00917 if (i > 0 || s[1] == '\0')
00918 return (i > 9) ? i : s[0];
00919 for (p = gui_key_map; p->s; p++) {
00920 if (!strcasecmp(p->s, s))
00921 return p->k;
00922 }
00923 return KEY_NONE;
00924 }
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 static int keypad_cfg_read(struct gui_info *gui, const char *val)
00936 {
00937 struct keypad_entry e;
00938 SDL_Rect *r = NULL;
00939 char s1[16], s2[16];
00940 int i, ret = 0;
00941
00942 if (gui == NULL || val == NULL)
00943 return 0;
00944
00945 s1[0] = s2[0] = '\0';
00946 memset(&e, '\0', sizeof(e));
00947 i = sscanf(val, "%14s %14s %d %d %d %d %d",
00948 s1, s2, &e.x0, &e.y0, &e.x1, &e.y1, &e.h);
00949
00950 e.c = gui_map_token(s1);
00951 if (e.c == KEY_NONE)
00952 return 0;
00953 switch (i) {
00954 default:
00955 break;
00956 case 1:
00957 if (e.c != KEY_RESET)
00958 break;
00959 if (gui->kp)
00960 gui->kp_used = 0;
00961 break;
00962 case 5:
00963 if (e.c == KEY_KEYPAD)
00964 r = &gui->kp_rect;
00965 else if (e.c == KEY_MESSAGE)
00966 r = gui->kp_msg;
00967 else if (e.c == KEY_DIALED)
00968 r = gui->kp_dialed;
00969 else if (e.c == KEY_EDIT)
00970 r = gui->kp_edit;
00971 if (r) {
00972 r->x = atoi(s2);
00973 r->y = e.x0;
00974 r->w = e.y0;
00975 r->h = e.x1;
00976 break;
00977 }
00978 if (strcasecmp(s2, "circle"))
00979 break;
00980
00981 e.h = e.x1;
00982 e.y1 = e.y0;
00983 e.x1 = e.x0 + e.h;
00984 e.x0 = e.x0 - e.h;
00985
00986
00987 case 7:
00988 if (e.c == KEY_FONT) {
00989 ast_log(LOG_WARNING, "font not supported yet\n");
00990 break;
00991 }
00992
00993 if (e.x1 < e.x0 || e.h <= 0) {
00994 ast_log(LOG_WARNING, "error in coordinates\n");
00995 e.type = 0;
00996 break;
00997 }
00998 if (!strcasecmp(s2, "circle")) {
00999
01000 e.type = KP_CIRCLE;
01001 e.x0 = (e.x1 + e.x0) / 2;
01002 e.y0 = (e.y1 + e.y0) / 2;
01003 e.h = e.h / 2;
01004 } else if (!strcasecmp(s2, "rect")) {
01005 e.type = KP_RECT;
01006 } else
01007 break;
01008 ret = 1;
01009 }
01010
01011 if (ret == 0)
01012 return 0;
01013 if (gui->kp_size == 0) {
01014 gui->kp = ast_calloc(10, sizeof(e));
01015 if (gui->kp == NULL) {
01016 ast_log(LOG_WARNING, "cannot allocate kp");
01017 return 0;
01018 }
01019 gui->kp_size = 10;
01020 }
01021 if (gui->kp_size == gui->kp_used) {
01022 struct keypad_entry *a = ast_realloc(gui->kp, sizeof(e)*(gui->kp_size+10));
01023 if (a == NULL) {
01024 ast_log(LOG_WARNING, "cannot reallocate kp");
01025 return 0;
01026 }
01027 gui->kp = a;
01028 gui->kp_size += 10;
01029 }
01030 if (gui->kp_size == gui->kp_used)
01031 return 0;
01032 gui->kp[gui->kp_used++] = e;
01033
01034 return 1;
01035 }
01036 #endif