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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 #include "asterisk.h"
00082 #include "console_video.h"
00083 #include "asterisk/lock.h"
00084 #include "asterisk/frame.h"
00085 #include "asterisk/utils.h"
00086 #include <math.h>
00087
00088
00089 enum { WIN_LOCAL, WIN_REMOTE, WIN_KEYPAD, WIN_SRC1,
00090 WIN_SRC2, WIN_SRC3, WIN_SRC4, WIN_SRC5,
00091 WIN_SRC6, WIN_SRC7, WIN_SRC8, WIN_SRC9, WIN_MAX };
00092
00093 #ifndef HAVE_SDL
00094 static void show_frame(struct video_desc *env, int out) {}
00095 static void sdl_setup(struct video_desc *env) {}
00096 static struct gui_info *cleanup_sdl(struct gui_info* g, int n) { return NULL; }
00097 static void eventhandler(struct video_desc *env, const char *caption) {}
00098 static int keypad_cfg_read(struct gui_info *gui, const char *val) { return 0; }
00099
00100 #else
00101
00102 #include <SDL/SDL.h>
00103 #include <SDL/SDL_syswm.h>
00104 #ifdef HAVE_SDL_IMAGE
00105 #include <SDL/SDL_image.h>
00106 #endif
00107
00108 #ifdef HAVE_X11
00109
00110 #include <X11/Xlib.h>
00111 #endif
00112
00113 #define BORDER 5
00114 #define SRC_MSG_BD_H 20
00115
00116 enum kp_type { KP_NONE, KP_RECT, KP_CIRCLE };
00117 struct keypad_entry {
00118 int c;
00119 int x0, y0, x1, y1, h;
00120 enum kp_type type;
00121 };
00122
00123
00124
00125
00126 struct display_window {
00127 SDL_Overlay *bmp;
00128 SDL_Rect rect;
00129 };
00130
00131
00132
00133 struct thumb_bd {
00134 SDL_Rect rect;
00135 struct board *board;
00136 };
00137
00138 struct gui_info {
00139 enum kb_output kb_output;
00140 struct drag_info drag;
00141
00142 SDL_Surface *screen;
00143
00144 int outfd;
00145 SDL_Surface *keypad;
00146 SDL_Rect kp_rect;
00147 SDL_Surface *font;
00148 SDL_Rect font_rects[96];
00149
00150
00151
00152
00153
00154
00155
00156 SDL_Rect kp_msg[2];
00157 struct board *bd_msg;
00158
00159 SDL_Rect kp_edit[2];
00160 struct board *bd_edit;
00161
00162 SDL_Rect kp_dialed[2];
00163 struct board *bd_dialed;
00164
00165
00166
00167
00168
00169 struct thumb_bd thumb_bd_array[MAX_VIDEO_SOURCES];
00170
00171
00172 int kp_size, kp_used;
00173 struct keypad_entry *kp;
00174
00175 struct display_window win[WIN_MAX];
00176 };
00177
00178
00179
00180
00181 static struct gui_info *cleanup_sdl(struct gui_info *gui, int device_num)
00182 {
00183 int i;
00184
00185 if (gui == NULL)
00186 return NULL;
00187
00188
00189 if (gui->font) {
00190 SDL_FreeSurface(gui->font);
00191 gui->font = NULL;
00192 }
00193
00194 if (gui->outfd > -1)
00195 close(gui->outfd);
00196 if (gui->keypad)
00197 SDL_FreeSurface(gui->keypad);
00198 gui->keypad = NULL;
00199 if (gui->kp)
00200 ast_free(gui->kp);
00201
00202
00203 for (i = 0; i < WIN_MAX; i++) {
00204 if (gui->win[i].bmp)
00205 SDL_FreeYUVOverlay(gui->win[i].bmp);
00206 }
00207 memset(gui, '\0', sizeof(gui));
00208
00209
00210 if (gui->bd_dialed)
00211 delete_board(gui->bd_dialed);
00212 if (gui->bd_msg)
00213 delete_board(gui->bd_msg);
00214
00215
00216 for (i = 0; i < device_num; i++) {
00217 if (gui->thumb_bd_array[i].board)
00218 delete_board(gui->thumb_bd_array[i].board);
00219 }
00220
00221 ast_free(gui);
00222 SDL_Quit();
00223 return NULL;
00224 }
00225
00226
00227
00228
00229
00230
00231 #define IS_PRIMARY 1
00232 #define IS_SECONDARY 2
00233 #define IS_ON 4
00234
00235 char* src_msgs[] = {
00236 " OFF",
00237 "1 OFF",
00238 " 2 OFF",
00239 "1+2 OFF",
00240 " ON",
00241 "1 ON",
00242 " 2 ON",
00243 "1+2 ON",
00244 };
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 static void show_frame(struct video_desc *env, int out)
00256 {
00257 AVPicture *p_in, p_out;
00258 struct fbuf_t *b_in, *b_out;
00259 SDL_Overlay *bmp;
00260 struct gui_info *gui = env->gui;
00261
00262 if (!gui)
00263 return;
00264
00265 if (out == WIN_LOCAL) {
00266 b_in = &env->enc_in;
00267 b_out = &env->loc_dpy;
00268 p_in = NULL;
00269 } else if (out == WIN_REMOTE) {
00270
00271 AVCodecContext *c;
00272 if (env->in == NULL)
00273 return;
00274 c = env->in->dec_ctx;
00275 b_in = &env->in->dec_out;
00276 b_in->pix_fmt = c->pix_fmt;
00277 b_in->w = c->width;
00278 b_in->h = c->height;
00279
00280 b_out = &env->rem_dpy;
00281 p_in = (AVPicture *)env->in->d_frame;
00282 } else {
00283 int i = out-WIN_SRC1;
00284 b_in = env->out.devices[i].dev_buf;
00285 if (b_in == NULL)
00286 return;
00287 p_in = NULL;
00288 b_out = &env->src_dpy[i];
00289 }
00290 bmp = gui->win[out].bmp;
00291 SDL_LockYUVOverlay(bmp);
00292
00293 memset(&p_out, '\0', sizeof(p_out));
00294 p_out.data[0] = bmp->pixels[0];
00295 p_out.data[1] = bmp->pixels[1];
00296 p_out.data[2] = bmp->pixels[2];
00297 p_out.linesize[0] = bmp->pitches[0];
00298 p_out.linesize[1] = bmp->pitches[1];
00299 p_out.linesize[2] = bmp->pitches[2];
00300
00301 my_scale(b_in, p_in, b_out, &p_out);
00302
00303
00304 SDL_DisplayYUVOverlay(bmp, &gui->win[out].rect);
00305 SDL_UnlockYUVOverlay(bmp);
00306 }
00307
00308
00309
00310
00311
00312
00313
00314 enum skin_area {
00315
00316 KEY_PICK_UP = 128,
00317 KEY_HANG_UP = 129,
00318
00319 KEY_MUTE = 130,
00320 KEY_AUTOANSWER = 131,
00321 KEY_SENDVIDEO = 132,
00322 KEY_LOCALVIDEO = 133,
00323 KEY_REMOTEVIDEO = 134,
00324 KEY_FLASH = 136,
00325
00326
00327 KEY_MESSAGEBOARD = 140,
00328 KEY_DIALEDBOARD = 141,
00329 KEY_EDITBOARD = 142,
00330
00331 KEY_GUI_CLOSE = 199,
00332
00333
00334
00335 KEY_KEYPAD = 200,
00336 KEY_FONT = 201,
00337 KEY_MESSAGE = 202,
00338 KEY_DIALED = 203,
00339 KEY_EDIT = 204,
00340
00341 #ifdef notyet
00342 KEY_AUDIO_SRCS = 210,
00343
00344
00345
00346
00347 #endif
00348
00349 KEY_FREEZE = 220,
00350 KEY_CAPTURE = 221,
00351 KEY_PIP = 230,
00352
00353
00354
00355 KEY_SRCS_WIN = 231,
00356
00357 KEY_OUT_OF_KEYPAD = 241,
00358 KEY_REM_DPY = 242,
00359 KEY_LOC_DPY = 243,
00360 KEY_RESET = 253,
00361 KEY_NONE = 254,
00362 KEY_DIGIT_BACKGROUND = 255,
00363 };
00364
00365
00366
00367
00368
00369
00370 static void keypad_digit(struct video_desc *env, int digit)
00371 {
00372 if (env->owner) {
00373 struct ast_frame f = { AST_FRAME_DTMF, 0 };
00374
00375 f.subclass = digit;
00376 ast_queue_frame(env->owner, &f);
00377 } else {
00378 char buf[2] = { digit, '\0' };
00379 if (env->gui->bd_msg)
00380 print_message(env->gui->bd_msg, buf);
00381 }
00382 }
00383
00384
00385 static char *keypad_toggle(struct video_desc *env, int index)
00386 {
00387 ast_log(LOG_WARNING, "keypad_toggle(%i) called\n", index);
00388
00389 switch (index) {
00390 case KEY_SENDVIDEO:
00391 env->out.sendvideo = !env->out.sendvideo;
00392 break;
00393
00394 case KEY_PIP:
00395 env->out.picture_in_picture = !env->out.picture_in_picture;
00396 break;
00397
00398 case KEY_MUTE:
00399 ast_cli_command(env->gui->outfd, "console mute toggle");
00400 break;
00401
00402 case KEY_FREEZE:
00403 env->frame_freeze = !env->frame_freeze;
00404 break;
00405
00406 #ifdef notyet
00407 case KEY_AUTOANSWER: {
00408 struct chan_oss_pvt *o = find_desc(oss_active);
00409 o->autoanswer = !o->autoanswer;
00410 }
00411 break;
00412 #endif
00413 }
00414 return NULL;
00415 }
00416
00417 char *console_do_answer(int fd);
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428 static void keypad_pick_up(struct video_desc *env)
00429 {
00430 struct gui_info *gui = env->gui;
00431
00432 ast_log(LOG_WARNING, "keypad_pick_up called\n");
00433
00434 if (env->owner) {
00435 ast_cli_command(gui->outfd, "console answer");
00436 } else {
00437 char buf[160];
00438 const char *who = ast_skip_blanks(read_message(gui->bd_msg));
00439 buf[sizeof(buf) - 1] = '\0';
00440 snprintf(buf, sizeof(buf), "console dial %s", who);
00441 ast_log(LOG_WARNING, "doing <%s>\n", buf);
00442 print_message(gui->bd_dialed, "\n");
00443 print_message(gui->bd_dialed, who);
00444 reset_board(gui->bd_msg);
00445 ast_cli_command(gui->outfd, buf);
00446 }
00447 }
00448
00449 #if 0
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 static int gui_output(struct video_desc *env, const char *text)
00469 {
00470 return 1;
00471 }
00472 #endif
00473
00474 static int video_geom(struct fbuf_t *b, const char *s);
00475 static void sdl_setup(struct video_desc *env);
00476 static int kp_match_area(const struct keypad_entry *e, int x, int y);
00477
00478 static void set_drag(struct drag_info *drag, int x, int y, enum drag_window win)
00479 {
00480 drag->x_start = x;
00481 drag->y_start = y;
00482 drag->drag_window = win;
00483 }
00484
00485 static int update_device_info(struct video_desc *env, int i)
00486 {
00487 reset_board(env->gui->thumb_bd_array[i].board);
00488 print_message(env->gui->thumb_bd_array[i].board,
00489 src_msgs[env->out.devices[i].status_index]);
00490 return 0;
00491 }
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 static int switch_video_out(struct video_desc *env, int index, Uint8 button)
00513 {
00514 int *p;
00515
00516 if (index >= env->out.device_num) {
00517 ast_log(LOG_WARNING, "no devices\n");
00518 return 1;
00519 }
00520
00521 p = (button == SDL_BUTTON_LEFT) ? &env->out.device_primary :
00522 &env->out.device_secondary;
00523
00524 if (index == *p) {
00525 ast_log(LOG_WARNING, "device %s already selected\n", env->out.devices[index].name);
00526 return 0;
00527 }
00528 ast_log(LOG_WARNING, "switching to %s...\n", env->out.devices[index].name);
00529
00530 if (env->out.devices[index].grabber) {
00531
00532
00533
00534 if (p == &env->out.device_primary)
00535 env->out.devices[*p].status_index &= ~IS_PRIMARY;
00536 else
00537 env->out.devices[*p].status_index &= ~IS_SECONDARY;
00538 update_device_info(env, *p);
00539
00540 *p = index;
00541 ast_log(LOG_WARNING, "done\n");
00542
00543 if (p == &env->out.device_primary)
00544 env->out.devices[*p].status_index |= IS_PRIMARY;
00545 else
00546 env->out.devices[*p].status_index |= IS_SECONDARY;
00547 update_device_info(env, *p);
00548 return 0;
00549 }
00550
00551 ast_log(LOG_WARNING, "device is down\n");
00552 return 1;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 static int turn_on_off(int index, struct video_desc *env)
00567 {
00568 struct video_device *p = &env->out.devices[index];
00569
00570 if (index >= env->out.device_num) {
00571 ast_log(LOG_WARNING, "no devices\n");
00572 return 0;
00573 }
00574
00575 if (!p->grabber) {
00576 void *g_data;
00577 struct grab_desc *g;
00578 int i;
00579
00580
00581 for (i = 0; (g = console_grabbers[i]); i++) {
00582
00583 g_data = g->open(p->name, &env->out.loc_src_geometry, env->out.fps);
00584 if (!g_data)
00585 continue;
00586 p->grabber = g;
00587 p->grabber_data = g_data;
00588
00589 p->status_index |= IS_ON;
00590
00591 update_device_info(env, index);
00592 return 1;
00593 }
00594 return 0;
00595 } else {
00596
00597 p->grabber_data = p->grabber->close(p->grabber_data);
00598 p->grabber = NULL;
00599
00600 p->dev_buf = NULL;
00601
00602 p->status_index &= ~IS_ON;
00603
00604 update_device_info(env, index);
00605 return 2;
00606 }
00607 }
00608
00609
00610
00611
00612
00613
00614
00615 static void handle_mousedown(struct video_desc *env, SDL_MouseButtonEvent button)
00616 {
00617 uint8_t index = KEY_OUT_OF_KEYPAD;
00618 struct gui_info *gui = env->gui;
00619
00620 int i;
00621
00622 int x;
00623
00624
00625 int src_wins_tot_w = env->out.device_num*(SRC_WIN_W+BORDER)+BORDER;
00626
00627
00628 int x0 = MAX(env->rem_dpy.w+gui->keypad->w/2+2*BORDER, src_wins_tot_w/2);
00629
00630 #if 0
00631 ast_log(LOG_WARNING, "event %d %d have %d/%d regions at %p\n",
00632 button.x, button.y, gui->kp_used, gui->kp_size, gui->kp);
00633 #endif
00634
00635 gui->drag.drag_window = DRAG_NONE;
00636
00637
00638
00639 if (button.y >= (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0)) {
00640
00641
00642
00643 button.y -= (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0);
00644 if (button.y < BORDER)
00645 index = KEY_OUT_OF_KEYPAD;
00646 else if (button.y >= MAX(MAX(env->rem_dpy.h, env->loc_dpy.h), gui->keypad->h))
00647 index = KEY_OUT_OF_KEYPAD;
00648 else if (button.x < x0 - gui->keypad->w/2 - BORDER - env->rem_dpy.w)
00649 index = KEY_OUT_OF_KEYPAD;
00650 else if (button.x < x0 - gui->keypad->w/2 - BORDER)
00651 index = KEY_REM_DPY;
00652 else if (button.x < x0 - gui->keypad->w/2)
00653 index = KEY_OUT_OF_KEYPAD;
00654 else if (button.x >= x0 + gui->keypad->w/2 + BORDER + env->loc_dpy.w)
00655 index = KEY_OUT_OF_KEYPAD;
00656 else if (button.x >= x0 + gui->keypad->w/2 + BORDER)
00657 index = KEY_LOC_DPY;
00658 else if (button.x >= x0 + gui->keypad->w/2)
00659 index = KEY_OUT_OF_KEYPAD;
00660 else if (gui->kp) {
00661
00662
00663 int x_keypad = button.x - (x0 - gui->keypad->w/2);
00664
00665 for (i = 0; i < gui->kp_used; i++) {
00666 if (kp_match_area(&gui->kp[i],x_keypad, button.y - BORDER)) {
00667 index = gui->kp[i].c;
00668 break;
00669 }
00670 }
00671 }
00672 } else if (button.y < BORDER) {
00673 index = KEY_OUT_OF_KEYPAD;
00674 } else {
00675 x = x0 - src_wins_tot_w/2 + BORDER;
00676 if (button.y >= BORDER + SRC_WIN_H)
00677 index = KEY_OUT_OF_KEYPAD;
00678 else if (button.x < x)
00679 index = KEY_OUT_OF_KEYPAD;
00680 else if (button.x < x + src_wins_tot_w - BORDER) {
00681
00682
00683
00684
00685 for (i = 1; i <= env->out.device_num; i++) {
00686 if (button.x < x+i*(SRC_WIN_W+BORDER)-BORDER) {
00687 index = KEY_SRCS_WIN+i-1;
00688 break;
00689 } else if (button.x < x+i*(SRC_WIN_W+BORDER)) {
00690 index = KEY_OUT_OF_KEYPAD;
00691 break;
00692 }
00693 }
00694 } else
00695 index = KEY_OUT_OF_KEYPAD;
00696 }
00697
00698
00699 if (index < 128) {
00700 keypad_digit(env, index);
00701 return;
00702 }
00703
00704 else if (index >= KEY_SRCS_WIN && index < KEY_SRCS_WIN+env->out.device_num) {
00705 index -= KEY_SRCS_WIN;
00706
00707
00708 if (button.button == SDL_BUTTON_RIGHT || button.button == SDL_BUTTON_LEFT) {
00709 switch_video_out(env, index, button.button);
00710 return;
00711 }
00712
00713 else {
00714 int ret = turn_on_off(index, env);
00715
00716 if (!ret)
00717 ast_log(LOG_WARNING, "unable to turn on device %s\n",
00718 env->out.devices[index].name);
00719 else if (ret == 1)
00720 ast_log(LOG_WARNING, "device %s changed state to on\n",
00721 env->out.devices[index].name);
00722 else if (ret == 2)
00723 ast_log(LOG_WARNING, "device %s changed state to off\n",
00724 env->out.devices[index].name);
00725 return;
00726 }
00727 }
00728
00729
00730
00731
00732
00733
00734 switch (index) {
00735
00736 case KEY_PICK_UP:
00737 keypad_pick_up(env);
00738 break;
00739 case KEY_HANG_UP:
00740 ast_cli_command(gui->outfd, "console hangup");
00741 break;
00742
00743
00744 case KEY_MUTE:
00745 case KEY_AUTOANSWER:
00746 case KEY_SENDVIDEO:
00747 case KEY_PIP:
00748 case KEY_FREEZE:
00749 keypad_toggle(env, index);
00750 break;
00751
00752 case KEY_LOCALVIDEO:
00753 break;
00754 case KEY_REMOTEVIDEO:
00755 break;
00756
00757 #ifdef notyet
00758 case KEY_CAPTURE:
00759 break;
00760 #endif
00761
00762 case KEY_MESSAGEBOARD:
00763 if (button.button == SDL_BUTTON_LEFT)
00764 set_drag(&gui->drag, button.x, button.y, DRAG_MESSAGE);
00765 break;
00766
00767
00768 case KEY_LOC_DPY:
00769 case KEY_REM_DPY:
00770 if (button.button == SDL_BUTTON_LEFT) {
00771
00772 int pip_loc_x = (double)env->out.pip_x/env->enc_in.w * env->loc_dpy.w;
00773 int pip_loc_y = (double)env->out.pip_y/env->enc_in.h * env->loc_dpy.h;
00774
00775 if (index == KEY_LOC_DPY && env->out.picture_in_picture &&
00776 button.x >= x0+gui->keypad->w/2+BORDER+pip_loc_x &&
00777 button.x < x0+gui->keypad->w/2+BORDER+pip_loc_x+env->loc_dpy.w/3 &&
00778 button.y >= BORDER+pip_loc_y &&
00779 button.y < BORDER+pip_loc_y+env->loc_dpy.h/3) {
00780
00781 button.y += (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0);
00782
00783 set_drag(&gui->drag, button.x, button.y, DRAG_PIP);
00784 }
00785 else if (index == KEY_LOC_DPY) {
00786
00787 button.y += (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0);
00788
00789 set_drag(&gui->drag, button.x, button.y, DRAG_LOCAL);
00790 }
00791 break;
00792 } else {
00793 char buf[128];
00794 struct fbuf_t *fb = index == KEY_LOC_DPY ? &env->loc_dpy : &env->rem_dpy;
00795 sprintf(buf, "%c%dx%d", button.button == SDL_BUTTON_RIGHT ? '>' : '<',
00796 fb->w, fb->h);
00797 video_geom(fb, buf);
00798 sdl_setup(env);
00799
00800
00801
00802
00803 for (i = 0; i < env->out.device_num; i++) {
00804 update_device_info(env, i);
00805 }
00806
00807
00808 print_message(gui->bd_msg, " \b");
00809 print_message(gui->bd_dialed, " \b");
00810 }
00811 break;
00812 case KEY_OUT_OF_KEYPAD:
00813 ast_log(LOG_WARNING, "nothing clicked, coordinates: %d, %d\n", button.x, button.y);
00814 break;
00815
00816 case KEY_DIGIT_BACKGROUND:
00817 break;
00818
00819 default:
00820 ast_log(LOG_WARNING, "function not yet defined %i\n", index);
00821 }
00822 }
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835 static const char * const us_kbd_map[] = {
00836 "`~", "1!", "2@", "3#", "4$", "5%", "6^",
00837 "7&", "8*", "9(", "0)", "-_", "=+", "[{",
00838 "]}", "\\|", ";:", "'\"", ",<", ".>", "/?",
00839 "jJ\n",
00840 NULL
00841 };
00842
00843 static char map_key(SDL_keysym *ks)
00844 {
00845 const char *s, **p = us_kbd_map;
00846 int c = ks->sym;
00847
00848 if (c == '\r')
00849 c = '\n';
00850 if (c >= SDLK_NUMLOCK && c <= SDLK_COMPOSE)
00851 return 0;
00852 if (ks->mod == 0)
00853 return c;
00854 while ((s = *p) && s[0] != c)
00855 p++;
00856 if (s) {
00857 int l = strlen(s), mod = 0;
00858 if (l > 1)
00859 mod |= (ks->mod & KMOD_SHIFT) ? 1 : 0;
00860 if (l > 2 + mod)
00861 mod |= (ks->mod & KMOD_CTRL) ? 2 : 0;
00862 if (l > 4 + mod)
00863 mod |= (ks->mod & KMOD_ALT) ? 4 : 0;
00864 c = s[mod];
00865 }
00866 if (ks->mod & (KMOD_CAPS|KMOD_SHIFT) && c >= 'a' && c <='z')
00867 c += 'A' - 'a';
00868 return c;
00869 }
00870
00871 static void handle_keyboard_input(struct video_desc *env, SDL_keysym *ks)
00872 {
00873 char buf[2] = { map_key(ks), '\0' };
00874 struct gui_info *gui = env->gui;
00875 if (buf[0] == 0)
00876 return;
00877 switch (gui->kb_output) {
00878 default:
00879 break;
00880 case KO_INPUT:
00881 break;
00882 case KO_MESSAGE:
00883 if (gui->bd_msg) {
00884 print_message(gui->bd_msg, buf);
00885 if (buf[0] == '\r' || buf[0] == '\n') {
00886 keypad_pick_up(env);
00887 }
00888 }
00889 break;
00890
00891 case KO_DIALED:
00892 break;
00893 }
00894
00895 return;
00896 }
00897
00898 static void grabber_move(struct video_device *, int dx, int dy);
00899
00900 int compute_drag(int *start, int end, int magnifier);
00901 int compute_drag(int *start, int end, int magnifier)
00902 {
00903 int delta = end - *start;
00904 #define POLARITY -1
00905
00906 delta += delta * delta * (delta > 0 ? 1 : -1 )/100;
00907 delta *= POLARITY * magnifier;
00908 #undef POLARITY
00909 *start = end;
00910 return delta;
00911 }
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921 static void pip_move(struct video_desc* env, int dx, int dy) {
00922 int new_pip_x = env->out.pip_x+dx;
00923 int new_pip_y = env->out.pip_y+dy;
00924
00925 if (new_pip_x < 0)
00926 new_pip_x = 0;
00927
00928 else if (new_pip_x > env->enc_in.w - env->enc_in.w/3)
00929 new_pip_x = env->enc_in.w - env->enc_in.w/3;
00930
00931 if (new_pip_y < 0)
00932 new_pip_y = 0;
00933
00934 else if (new_pip_y > env->enc_in.h - env->enc_in.h/3)
00935 new_pip_y = env->enc_in.h - env->enc_in.h/3;
00936 env->out.pip_x = new_pip_x;
00937 env->out.pip_y = new_pip_y;
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949 static void eventhandler(struct video_desc *env, const char *caption)
00950 {
00951 struct gui_info *gui = env->gui;
00952 struct drag_info *drag;
00953 #define N_EVENTS 32
00954 int i, n;
00955 SDL_Event ev[N_EVENTS];
00956
00957 if (!gui)
00958 return;
00959 drag = &gui->drag;
00960 if (caption)
00961 SDL_WM_SetCaption(caption, NULL);
00962
00963 #define MY_EV (SDL_MOUSEBUTTONDOWN|SDL_KEYDOWN)
00964 while ( (n = SDL_PeepEvents(ev, N_EVENTS, SDL_GETEVENT, SDL_ALLEVENTS)) > 0) {
00965 for (i = 0; i < n; i++) {
00966 #if 0
00967 ast_log(LOG_WARNING, "------ event %d at %d %d\n",
00968 ev[i].type, ev[i].button.x, ev[i].button.y);
00969 #endif
00970 switch (ev[i].type) {
00971 default:
00972 ast_log(LOG_WARNING, "------ event %d at %d %d\n",
00973 ev[i].type, ev[i].button.x, ev[i].button.y);
00974 break;
00975
00976 case SDL_ACTIVEEVENT:
00977 #if 0
00978 if (ev[i].active.gain == 0 && ev[i].active.state & SDL_APPACTIVE) {
00979 ast_log(LOG_WARNING, "/* somebody has killed us ? */");
00980 ast_cli_command(gui->outfd, "stop now");
00981 }
00982 #endif
00983 break;
00984
00985 case SDL_KEYUP:
00986 break;
00987
00988 case SDL_KEYDOWN:
00989 handle_keyboard_input(env, &ev[i].key.keysym);
00990 break;
00991
00992 case SDL_MOUSEMOTION:
00993 case SDL_MOUSEBUTTONUP:
00994 if (drag->drag_window == DRAG_LOCAL && env->out.device_num) {
00995
00996 int dx = compute_drag(&drag->x_start, ev[i].motion.x, 3);
00997 int dy = compute_drag(&drag->y_start, ev[i].motion.y, 3);
00998 grabber_move(&env->out.devices[env->out.device_primary], dx, dy);
00999 } else if (drag->drag_window == DRAG_PIP) {
01000
01001 int dx = ev[i].motion.x - drag->x_start;
01002 int dy = ev[i].motion.y - drag->y_start;
01003
01004
01005 dx = (double)dx*env->enc_in.w/env->loc_dpy.w;
01006 dy = (double)dy*env->enc_in.h/env->loc_dpy.h;
01007
01008 drag->x_start = ev[i].motion.x;
01009 drag->y_start = ev[i].motion.y;
01010
01011 pip_move(env, dx, dy);
01012 } else if (drag->drag_window == DRAG_MESSAGE) {
01013
01014 int dy = compute_drag(&drag->y_start, ev[i].motion.y, 1);
01015 move_message_board(gui->bd_msg, dy);
01016 }
01017 if (ev[i].type == SDL_MOUSEBUTTONUP)
01018 drag->drag_window = DRAG_NONE;
01019 break;
01020 case SDL_MOUSEBUTTONDOWN:
01021 handle_mousedown(env, ev[i].button);
01022 break;
01023 }
01024 }
01025 }
01026 if (1) {
01027 struct timeval b, a = ast_tvnow();
01028 int i;
01029
01030 SDL_PumpEvents();
01031 b = ast_tvnow();
01032 i = ast_tvdiff_ms(b, a);
01033 if (i > 3)
01034 fprintf(stderr, "-------- SDL_PumpEvents took %dms\n", i);
01035
01036 }
01037 }
01038
01039 static SDL_Surface *load_image(const char *file)
01040 {
01041 SDL_Surface *temp;
01042
01043 #ifdef HAVE_SDL_IMAGE
01044 temp = IMG_Load(file);
01045 #else
01046 temp = SDL_LoadBMP(file);
01047 #endif
01048 if (temp == NULL)
01049 fprintf(stderr, "Unable to load image %s: %s\n",
01050 file, SDL_GetError());
01051 return temp;
01052 }
01053
01054 static void keypad_setup(struct gui_info *gui, const char *kp_file);
01055
01056
01057
01058 static struct gui_info *gui_init(const char *keypad_file, const char *font)
01059 {
01060 struct gui_info *gui = ast_calloc(1, sizeof(*gui));
01061
01062 if (gui == NULL)
01063 return NULL;
01064
01065 gui->kb_output = KO_MESSAGE;
01066 gui->drag.drag_window = DRAG_NONE;
01067 gui->outfd = -1;
01068
01069 keypad_setup(gui, keypad_file);
01070 if (gui->keypad == NULL)
01071 return gui;
01072
01073 if (!ast_strlen_zero(font)) {
01074 int i;
01075 SDL_Rect *r;
01076
01077 gui->font = load_image(font);
01078 if (!gui->font) {
01079 ast_log(LOG_WARNING, "Unable to load font %s, no output available\n", font);
01080 goto error;
01081 }
01082 ast_log(LOG_WARNING, "Loaded font %s\n", font);
01083
01084 r = gui->font_rects;
01085 #define FONT_H 20
01086 #define FONT_W 9
01087 for (i = 0; i < 96; r++, i++) {
01088 r->x = (i % 32 ) * FONT_W;
01089 r->y = (i / 32 ) * FONT_H;
01090 r->w = FONT_W;
01091 r->h = FONT_H;
01092 }
01093 }
01094
01095 gui->outfd = open ("/dev/null", O_WRONLY);
01096 if (gui->outfd < 0) {
01097 ast_log(LOG_WARNING, "Unable output fd\n");
01098 goto error;
01099 }
01100 return gui;
01101
01102 error:
01103 ast_free(gui);
01104 return NULL;
01105 }
01106
01107
01108 static int set_win(SDL_Surface *screen, struct display_window *win, int fmt,
01109 int w, int h, int x, int y)
01110 {
01111 win->bmp = SDL_CreateYUVOverlay(w, h, fmt, screen);
01112 if (win->bmp == NULL)
01113 return -1;
01114 win->rect.x = x;
01115 win->rect.y = y;
01116 win->rect.w = w;
01117 win->rect.h = h;
01118 return 0;
01119 }
01120
01121 static int keypad_cfg_read(struct gui_info *gui, const char *val);
01122
01123 static void keypad_setup(struct gui_info *gui, const char *kp_file)
01124 {
01125 FILE *fd;
01126 char buf[1024];
01127 const char region[] = "region";
01128 int reg_len = strlen(region);
01129 int in_comment = 0;
01130
01131 if (gui->keypad)
01132 return;
01133 gui->keypad = load_image(kp_file);
01134 if (!gui->keypad)
01135 return;
01136
01137 fd = fopen(kp_file, "r");
01138 if (fd == NULL) {
01139 ast_log(LOG_WARNING, "fail to open %s\n", kp_file);
01140 return;
01141 }
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151 while (fgets(buf, sizeof(buf), fd)) {
01152 char *s;
01153
01154 if (!strstr(buf, region)) {
01155 if (!in_comment)
01156 continue;
01157 else
01158 break;
01159 }
01160 if (!in_comment) {
01161 keypad_cfg_read(gui, "reset");
01162 in_comment = 1;
01163 }
01164 s = ast_skip_blanks(buf);
01165 ast_trim_blanks(s);
01166 if (memcmp(s, region, reg_len))
01167 break;
01168 s = ast_skip_blanks(s + reg_len);
01169 if (*s++ != '=')
01170 break;
01171 if (*s == '>')
01172 s++;
01173 keypad_cfg_read(gui, ast_skip_blanks(s));
01174 }
01175 fclose(fd);
01176 }
01177
01178 struct board *board_setup(SDL_Surface *screen, SDL_Rect *dest,
01179 SDL_Surface *font, SDL_Rect *font_rects);
01180
01181
01182 static void init_board(struct gui_info *gui, struct board **dst, SDL_Rect *r, int dx, int dy)
01183 {
01184 if (r[0].w == 0 || r[0].h == 0)
01185 return;
01186 r[1] = r[0];
01187 r[1].x += dx;
01188 r[1].y += dy;
01189 if (*dst == NULL) {
01190 *dst = board_setup(gui->screen, &r[1], gui->font, gui->font_rects);
01191 } else {
01192
01193 }
01194 }
01195
01196 #ifdef HAVE_X11
01197
01198
01199
01200
01201
01202
01203
01204 static int my_x_handler(Display *d, XErrorEvent *e)
01205 {
01206 ast_log(LOG_WARNING, "%s error_code %d\n", __FUNCTION__, e->error_code);
01207 return 0;
01208 }
01209 #endif
01210
01211
01212
01213
01214
01215 static void sdl_setup(struct video_desc *env)
01216 {
01217 int dpy_fmt = SDL_IYUV_OVERLAY;
01218 int depth, maxw, maxh;
01219 const SDL_VideoInfo *info;
01220 int kp_w = 0, kp_h = 0;
01221 struct gui_info *gui = env->gui;
01222
01223
01224 int x0;
01225 int x1;
01226 int y0;
01227 int src_wins_tot_w;
01228 int i;
01229 int x;
01230
01231 #ifdef HAVE_X11
01232 const char *e = getenv("SDL_WINDOWID");
01233
01234 if (!ast_strlen_zero(e)) {
01235 XWindowAttributes a;
01236 int (*old_x_handler)(Display *d, XErrorEvent *e) = XSetErrorHandler(my_x_handler);
01237 Display *d = XOpenDisplay(getenv("DISPLAY"));
01238 long w = atol(e);
01239 int success = w ? XGetWindowAttributes(d, w, &a) : 0;
01240
01241 XSetErrorHandler(old_x_handler);
01242 if (!success) {
01243 ast_log(LOG_WARNING, "%s error in window\n", __FUNCTION__);
01244 return;
01245 }
01246 }
01247 #endif
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261 if (gui == NULL && SDL_Init(SDL_INIT_VIDEO)) {
01262 ast_log(LOG_WARNING, "Could not initialize SDL - %s\n",
01263 SDL_GetError());
01264
01265 return;
01266 }
01267 info = SDL_GetVideoInfo();
01268
01269
01270
01271 if (!info || !info->vfmt) {
01272 ast_log(LOG_WARNING, "Bad SDL_GetVideoInfo - %s\n",
01273 SDL_GetError());
01274 return;
01275 }
01276 depth = info->vfmt->BitsPerPixel;
01277 if (depth < 16)
01278 depth = 16;
01279 if (!gui)
01280 env->gui = gui = gui_init(env->keypad_file, env->keypad_font);
01281 if (!gui)
01282 goto no_sdl;
01283
01284 if (gui->keypad) {
01285 if (gui->kp_rect.w > 0 && gui->kp_rect.h > 0) {
01286 kp_w = gui->kp_rect.w;
01287 kp_h = gui->kp_rect.h;
01288 } else {
01289 kp_w = gui->keypad->w;
01290 kp_h = gui->keypad->h;
01291 }
01292 }
01293
01294
01295 src_wins_tot_w = env->out.device_num*(SRC_WIN_W+BORDER)+BORDER;
01296
01297
01298 x0 = MAX(env->rem_dpy.w+kp_w/2+2*BORDER, src_wins_tot_w/2);
01299
01300
01301 x1 = MAX(env->loc_dpy.w+kp_w/2+2*BORDER, src_wins_tot_w/2);
01302
01303
01304 maxw = x0+x1;
01305
01306
01307 maxh = MAX( MAX(env->rem_dpy.h, env->loc_dpy.h), kp_h)+2*BORDER;
01308 maxh += env->out.device_num ? (2*BORDER+SRC_WIN_H+SRC_MSG_BD_H) : 0;
01309
01310 gui->screen = SDL_SetVideoMode(maxw, maxh, depth, 0);
01311 if (!gui->screen) {
01312 ast_log(LOG_ERROR, "SDL: could not set video mode - exiting\n");
01313 goto no_sdl;
01314 }
01315
01316 #ifdef HAVE_X11
01317
01318
01319
01320
01321
01322
01323 do {
01324
01325 XWindowAttributes attr;
01326 long want;
01327 SDL_SysWMinfo info;
01328 Display *SDL_Display;
01329 Window win;
01330
01331 const char *e = getenv("SDL_WINDOWID");
01332 if (ast_strlen_zero(e))
01333 break;
01334 SDL_VERSION(&info.version);
01335 if (SDL_GetWMInfo(&info) != 1) {
01336 fprintf(stderr, "no wm info\n");
01337 break;
01338 }
01339 SDL_Display = info.info.x11.display;
01340 if (SDL_Display == NULL)
01341 break;
01342 win = info.info.x11.window;
01343
01344
01345
01346
01347
01348 want = KeyPressMask | KeyReleaseMask | ButtonPressMask |
01349 ButtonReleaseMask | EnterWindowMask |
01350 LeaveWindowMask | PointerMotionMask |
01351 Button1MotionMask |
01352 Button2MotionMask | Button3MotionMask |
01353 Button4MotionMask | Button5MotionMask |
01354 ButtonMotionMask | KeymapStateMask |
01355 ExposureMask | VisibilityChangeMask |
01356 StructureNotifyMask |
01357 SubstructureNotifyMask | SubstructureRedirectMask |
01358 FocusChangeMask | PropertyChangeMask |
01359 ColormapChangeMask | OwnerGrabButtonMask;
01360
01361 memset(&attr, '\0', sizeof(attr));
01362 XGetWindowAttributes(SDL_Display, win, &attr);
01363
01364
01365
01366
01367
01368 {
01369
01370 long ev = ButtonPressMask | ResizeRedirectMask |
01371 SubstructureRedirectMask;
01372 ev &= (attr.all_event_masks & ~attr.your_event_mask);
01373
01374
01375
01376
01377 want &= ~ev;
01378 want |= attr.your_event_mask;
01379 }
01380 XSelectInput(SDL_Display, win, want);
01381
01382
01383
01384
01385
01386
01387
01388 XResizeWindow(SDL_Display, win, maxw, maxh);
01389 {
01390 XConfigureEvent ce = {
01391 .type = ConfigureNotify,
01392 .serial = 0,
01393 .send_event = 1,
01394 .display = SDL_Display,
01395 .event = win,
01396 .window = win,
01397 .x = 0,
01398 .y = 0,
01399 .width = maxw,
01400 .height = maxh,
01401 .border_width = 0,
01402 .above = 0,
01403 .override_redirect = 0 };
01404 XSendEvent(SDL_Display, win, 1 , StructureNotifyMask, (XEvent *)&ce);
01405 }
01406 } while (0);
01407 #endif
01408
01409 y0 = env->out.device_num ? (3*BORDER+SRC_WIN_H+SRC_MSG_BD_H) : BORDER;
01410
01411 SDL_WM_SetCaption("Asterisk console Video Output", NULL);
01412
01413
01414 if (set_win(gui->screen, &gui->win[WIN_REMOTE], dpy_fmt,
01415 env->rem_dpy.w, env->rem_dpy.h, x0-kp_w/2-BORDER-env->rem_dpy.w, y0))
01416 goto no_sdl;
01417
01418 env->frame_freeze = 0;
01419
01420 if (set_win(gui->screen, &gui->win[WIN_LOCAL], dpy_fmt,
01421 env->loc_dpy.w, env->loc_dpy.h,
01422 x0+kp_w/2+BORDER, y0))
01423 goto no_sdl;
01424
01425
01426
01427 x = x0 - src_wins_tot_w/2 + BORDER;
01428 for (i = 0; i < env->out.device_num; i++){
01429 struct thumb_bd *p = &gui->thumb_bd_array[i];
01430 if (set_win(gui->screen, &gui->win[i+WIN_SRC1], dpy_fmt,
01431 SRC_WIN_W, SRC_WIN_H, x+i*(BORDER+SRC_WIN_W), BORDER))
01432 goto no_sdl;
01433
01434 p->rect.w = SRC_WIN_W;
01435 p->rect.h = SRC_MSG_BD_H;
01436 p->rect.x = x+i*(BORDER+SRC_WIN_W);
01437 p->rect.y = 2*BORDER+SRC_WIN_H;
01438
01439 SDL_FillRect(gui->screen, &p->rect,
01440 SDL_MapRGB(gui->screen->format, 255, 255, 255));
01441
01442 if (!p->board)
01443 p->board =
01444 board_setup(gui->screen, &p->rect,
01445 gui->font, gui->font_rects);
01446
01447 SDL_UpdateRect(gui->screen, p->rect.x, p->rect.y, p->rect.w, p->rect.h);
01448 }
01449
01450
01451
01452 if (gui->keypad) {
01453 struct SDL_Rect *dest = &gui->win[WIN_KEYPAD].rect;
01454 struct SDL_Rect *src = (gui->kp_rect.w > 0 && gui->kp_rect.h > 0) ? & gui->kp_rect : NULL;
01455
01456 dest->x = x0-kp_w/2;
01457 dest->y = y0;
01458 dest->w = kp_w;
01459 dest->h = kp_h;
01460 SDL_BlitSurface(gui->keypad, src, gui->screen, dest);
01461 init_board(gui, &gui->bd_msg, gui->kp_msg, dest->x, dest->y);
01462 init_board(gui, &gui->bd_dialed, gui->kp_dialed, dest->x, dest->y);
01463 SDL_UpdateRects(gui->screen, 1, dest);
01464 }
01465 return;
01466
01467 no_sdl:
01468
01469 env->gui = cleanup_sdl(gui, env->out.device_num);
01470 }
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483 static int kp_match_area(const struct keypad_entry *e, int x, int y)
01484 {
01485 double xp, dx = (e->x1 - e->x0);
01486 double yp, dy = (e->y1 - e->y0);
01487 double l = sqrt(dx*dx + dy*dy);
01488 int ret = 0;
01489
01490 if (l > 1) {
01491 xp = ((x - e->x0)*dx + (y - e->y0)*dy)/l;
01492 yp = (-(x - e->x0)*dy + (y - e->y0)*dx)/l;
01493 if (e->type == KP_RECT) {
01494 ret = (xp >= 0 && xp < l && yp >=0 && yp < e->h);
01495 } else if (e->type == KP_CIRCLE) {
01496 dx = xp*xp/(l*l) + yp*yp/(e->h*e->h);
01497 ret = (dx < 1);
01498 }
01499 }
01500 #if 0
01501 ast_log(LOG_WARNING, "result %d [%d] for match %d,%d in type %d p0 %d,%d p1 %d,%d h %d\n",
01502 ret, e->c, x, y, e->type, e->x0, e->y0, e->x1, e->y1, e->h);
01503 #endif
01504 return ret;
01505 }
01506
01507 struct _s_k { const char *s; int k; };
01508 static const struct _s_k gui_key_map[] = {
01509 {"FREEZE", KEY_FREEZE},
01510 {"PIP", KEY_PIP},
01511 {"PICK_UP", KEY_PICK_UP },
01512 {"PICKUP", KEY_PICK_UP },
01513 {"HANG_UP", KEY_HANG_UP },
01514 {"HANGUP", KEY_HANG_UP },
01515 {"MUTE", KEY_MUTE },
01516 {"FLASH", KEY_FLASH },
01517 {"AUTOANSWER", KEY_AUTOANSWER },
01518 {"SENDVIDEO", KEY_SENDVIDEO },
01519 {"LOCALVIDEO", KEY_LOCALVIDEO },
01520 {"REMOTEVIDEO", KEY_REMOTEVIDEO },
01521 {"GUI_CLOSE", KEY_GUI_CLOSE },
01522 {"MESSAGEBOARD", KEY_MESSAGEBOARD },
01523 {"DIALEDBOARD", KEY_DIALEDBOARD },
01524 {"EDITBOARD", KEY_EDITBOARD },
01525 {"KEYPAD", KEY_KEYPAD },
01526 {"MESSAGE", KEY_MESSAGE },
01527 {"DIALED", KEY_DIALED },
01528 {"EDIT", KEY_EDIT },
01529 {"FONT", KEY_FONT },
01530 {NULL, 0 } };
01531
01532 static int gui_map_token(const char *s)
01533 {
01534
01535 int i = atoi(s);
01536 struct _s_k *p;
01537 if (i > 0 || s[1] == '\0')
01538 return (i > 9) ? i : s[0];
01539 for (p = gui_key_map; p->s; p++) {
01540 if (!strcasecmp(p->s, s))
01541 return p->k;
01542 }
01543 return KEY_NONE;
01544 }
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557 static int keypad_cfg_read(struct gui_info *gui, const char *val)
01558 {
01559 struct keypad_entry e;
01560 SDL_Rect *r = NULL;
01561 char s1[16], s2[16];
01562 int i, ret = 0;
01563
01564 if (gui == NULL || val == NULL)
01565 return 0;
01566
01567 s1[0] = s2[0] = '\0';
01568 memset(&e, '\0', sizeof(e));
01569 i = sscanf(val, "%14s %14s %d %d %d %d %d",
01570 s1, s2, &e.x0, &e.y0, &e.x1, &e.y1, &e.h);
01571
01572 e.c = gui_map_token(s1);
01573 if (e.c == KEY_NONE)
01574 return 0;
01575 switch (i) {
01576 default:
01577 break;
01578 case 1:
01579 if (e.c != KEY_RESET)
01580 break;
01581 if (gui->kp)
01582 gui->kp_used = 0;
01583 break;
01584 case 5:
01585 if (e.c == KEY_KEYPAD)
01586 r = &gui->kp_rect;
01587 else if (e.c == KEY_MESSAGE)
01588 r = gui->kp_msg;
01589 else if (e.c == KEY_DIALED)
01590 r = gui->kp_dialed;
01591 else if (e.c == KEY_EDIT)
01592 r = gui->kp_edit;
01593 if (r) {
01594 r->x = atoi(s2);
01595 r->y = e.x0;
01596 r->w = e.y0;
01597 r->h = e.x1;
01598 break;
01599 }
01600 if (strcasecmp(s2, "circle"))
01601 break;
01602
01603 e.h = e.x1;
01604 e.y1 = e.y0;
01605 e.x1 = e.x0 + e.h;
01606 e.x0 = e.x0 - e.h;
01607
01608
01609 case 7:
01610 if (e.c == KEY_FONT) {
01611 ast_log(LOG_WARNING, "font not supported yet\n");
01612 break;
01613 }
01614
01615 if (e.x1 < e.x0 || e.h <= 0) {
01616 ast_log(LOG_WARNING, "error in coordinates\n");
01617 e.type = 0;
01618 break;
01619 }
01620 if (!strcasecmp(s2, "circle")) {
01621
01622 e.type = KP_CIRCLE;
01623 e.x0 = (e.x1 + e.x0) / 2;
01624 e.y0 = (e.y1 + e.y0) / 2;
01625 e.h = e.h / 2;
01626 } else if (!strcasecmp(s2, "rect")) {
01627 e.type = KP_RECT;
01628 } else
01629 break;
01630 ret = 1;
01631 }
01632
01633 if (ret == 0)
01634 return 0;
01635 if (gui->kp_size == 0) {
01636 gui->kp = ast_calloc(10, sizeof(e));
01637 if (gui->kp == NULL) {
01638 ast_log(LOG_WARNING, "cannot allocate kp");
01639 return 0;
01640 }
01641 gui->kp_size = 10;
01642 }
01643 if (gui->kp_size == gui->kp_used) {
01644 struct keypad_entry *a = ast_realloc(gui->kp, sizeof(e)*(gui->kp_size+10));
01645 if (a == NULL) {
01646 ast_log(LOG_WARNING, "cannot reallocate kp");
01647 return 0;
01648 }
01649 gui->kp = a;
01650 gui->kp_size += 10;
01651 }
01652 if (gui->kp_size == gui->kp_used)
01653 return 0;
01654 gui->kp[gui->kp_used++] = e;
01655
01656 return 1;
01657 }
01658 #endif