#include "asterisk.h"
#include "console_video.h"
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/utils.h"
#include <math.h>
#include <SDL/SDL.h>
#include <SDL/SDL_syswm.h>
#include <X11/Xlib.h>
Go to the source code of this file.
Data Structures | |
struct | _s_k |
struct | display_window |
struct | gui_info |
struct | keypad_entry |
struct | thumb_bd |
Defines | |
#define | BORDER 5 |
#define | FONT_H 20 |
#define | FONT_W 9 |
#define | IS_ON 4 |
#define | IS_PRIMARY 1 |
#define | IS_SECONDARY 2 |
#define | MY_EV (SDL_MOUSEBUTTONDOWN|SDL_KEYDOWN) |
#define | N_EVENTS 32 |
#define | POLARITY -1 |
#define | SRC_MSG_BD_H 20 |
Enumerations | |
enum | { WIN_LOCAL, WIN_REMOTE, WIN_KEYPAD, WIN_SRC1, WIN_SRC2, WIN_SRC3, WIN_SRC4, WIN_SRC5, WIN_SRC6, WIN_SRC7, WIN_SRC8, WIN_SRC9, WIN_MAX } |
enum | kp_type { KP_NONE, KP_RECT, KP_CIRCLE } |
enum | skin_area { KEY_PICK_UP = 128, KEY_HANG_UP = 129, KEY_MUTE = 130, KEY_AUTOANSWER = 131, KEY_SENDVIDEO = 132, KEY_LOCALVIDEO = 133, KEY_REMOTEVIDEO = 134, KEY_FLASH = 136, KEY_MESSAGEBOARD = 140, KEY_DIALEDBOARD = 141, KEY_EDITBOARD = 142, KEY_GUI_CLOSE = 199, KEY_KEYPAD = 200, KEY_FONT = 201, KEY_MESSAGE = 202, KEY_DIALED = 203, KEY_EDIT = 204, KEY_FREEZE = 220, KEY_CAPTURE = 221, KEY_PIP = 230, KEY_SRCS_WIN = 231, KEY_OUT_OF_KEYPAD = 241, KEY_REM_DPY = 242, KEY_LOC_DPY = 243, KEY_RESET = 253, KEY_NONE = 254, KEY_DIGIT_BACKGROUND = 255 } |
Functions | |
board * | board_setup (SDL_Surface *screen, SDL_Rect *dest, SDL_Surface *font, SDL_Rect *font_rects) |
static struct gui_info * | cleanup_sdl (struct gui_info *gui, int device_num) |
free the resources in struct gui_info and the descriptor itself. Return NULL so we can assign the value back to the descriptor in case. | |
int | compute_drag (int *start, int end, int magnifier) |
char * | console_do_answer (int fd) |
static void | eventhandler (struct video_desc *env, const char *caption) |
refresh the screen, and also grab a bunch of events. | |
static void | grabber_move (struct video_device *, int dx, int dy) |
static struct gui_info * | gui_init (const char *keypad_file, const char *font) |
static int | gui_map_token (const char *s) |
static void | handle_keyboard_input (struct video_desc *env, SDL_keysym *ks) |
static void | handle_mousedown (struct video_desc *env, SDL_MouseButtonEvent button) |
static void | init_board (struct gui_info *gui, struct board **dst, SDL_Rect *r, int dx, int dy) |
initialize the boards we have in the keypad | |
static int | keypad_cfg_read (struct gui_info *gui, const char *val) |
read a keypad entry line in the format reset token circle xc yc diameter token circle xc yc x1 y1 h # ellipse, main diameter and height token rect x0 y0 x1 y1 h # rectangle with main side and eight token x0 y0 w h # horizontal rectangle (short format) # this is used e.g. for message boards token is the token to be returned, either a character or a symbol as KEY_* above Return 1 on success, 0 on error. | |
static void | keypad_digit (struct video_desc *env, int digit) |
static void | keypad_pick_up (struct video_desc *env) |
static void | keypad_setup (struct gui_info *gui, const char *kp_file) |
static char * | keypad_toggle (struct video_desc *env, int index) |
static int | kp_match_area (const struct keypad_entry *e, int x, int y) |
static SDL_Surface * | load_image (const char *file) |
static char | map_key (SDL_keysym *ks) |
static int | my_x_handler (Display *d, XErrorEvent *e) |
static void | pip_move (struct video_desc *env, int dx, int dy) |
This function moves the picture in picture, controlling the limits of the containing buffer to avoid problems deriving from going through the limits. | |
static void | sdl_setup (struct video_desc *env) |
[re]set the main sdl window, useful in case of resize. We can tell the first from subsequent calls from the value of env->gui, which is NULL the first time. | |
static void | set_drag (struct drag_info *drag, int x, int y, enum drag_window win) |
static int | set_win (SDL_Surface *screen, struct display_window *win, int fmt, int w, int h, int x, int y) |
static void | show_frame (struct video_desc *env, int out) |
static int | switch_video_out (struct video_desc *env, int index, Uint8 button) |
Changes the video output (local video) source, controlling if it is already using that video device, and switching the correct fields of env->out. grabbers are always open and saved in the device table. The secondary or the primary device can be changed, according to the "button" parameter: the primary device is changed if button = SDL_BUTTON_LEFT; the secondary device is changed if button = not SDL_BUTTON_LEFT;. | |
static int | turn_on_off (int index, struct video_desc *env) |
tries to switch the state of a device from on to off or off to on we also have to update the status of the device and the correct message board | |
static int | update_device_info (struct video_desc *env, int i) |
static int | video_geom (struct fbuf_t *b, const char *s) |
Variables | |
static struct _s_k | gui_key_map [] |
char * | src_msgs [] |
static const char *const | us_kbd_map [] |
#define BORDER 5 |
#define FONT_H 20 |
#define FONT_W 9 |
#define IS_ON 4 |
#define IS_PRIMARY 1 |
#define IS_SECONDARY 2 |
#define MY_EV (SDL_MOUSEBUTTONDOWN|SDL_KEYDOWN) |
#define N_EVENTS 32 |
Referenced by eventhandler().
#define POLARITY -1 |
Referenced by compute_drag().
#define SRC_MSG_BD_H 20 |
anonymous enum |
WIN_LOCAL | |
WIN_REMOTE | |
WIN_KEYPAD | |
WIN_SRC1 | |
WIN_SRC2 | |
WIN_SRC3 | |
WIN_SRC4 | |
WIN_SRC5 | |
WIN_SRC6 | |
WIN_SRC7 | |
WIN_SRC8 | |
WIN_SRC9 | |
WIN_MAX |
Definition at line 93 of file console_gui.c.
00093 { WIN_LOCAL, WIN_REMOTE, WIN_KEYPAD, WIN_SRC1, 00094 WIN_SRC2, WIN_SRC3, WIN_SRC4, WIN_SRC5, 00095 WIN_SRC6, WIN_SRC7, WIN_SRC8, WIN_SRC9, WIN_MAX };
enum kp_type |
enum skin_area |
Definition at line 318 of file console_gui.c.
00318 { 00319 /* answer/close functions */ 00320 KEY_PICK_UP = 128, 00321 KEY_HANG_UP = 129, 00322 00323 KEY_MUTE = 130, 00324 KEY_AUTOANSWER = 131, 00325 KEY_SENDVIDEO = 132, 00326 KEY_LOCALVIDEO = 133, 00327 KEY_REMOTEVIDEO = 134, 00328 KEY_FLASH = 136, 00329 00330 /* sensitive areas for the various text windows */ 00331 KEY_MESSAGEBOARD = 140, 00332 KEY_DIALEDBOARD = 141, 00333 KEY_EDITBOARD = 142, 00334 00335 KEY_GUI_CLOSE = 199, /* close gui */ 00336 /* regions of the skin - displayed area, fonts, etc. 00337 * XXX NOTE these are not sensitive areas. 00338 */ 00339 KEY_KEYPAD = 200, /* the keypad - default to the whole image */ 00340 KEY_FONT = 201, /* the font. Maybe not really useful */ 00341 KEY_MESSAGE = 202, /* area for incoming messages */ 00342 KEY_DIALED = 203, /* area for dialed numbers */ 00343 KEY_EDIT = 204, /* area for editing user input */ 00344 00345 #ifdef notyet /* XXX for future implementation */ 00346 KEY_AUDIO_SRCS = 210, 00347 /*indexes between 210 and 219 (or more) have been reserved for the "keys" 00348 associated with the audio device markers, clicking on these markers 00349 will change the source device for audio output */ 00350 00351 #endif 00352 /* Keys related to video sources */ 00353 KEY_FREEZE = 220, /* freeze the incoming video */ 00354 KEY_CAPTURE = 221, /* capture the whole SDL window as a picture */ 00355 KEY_PIP = 230, 00356 /*indexes between 231 and 239 have been reserved for the "keys" 00357 associated with the device thumbnails, clicking on these pictures 00358 will change the source device for primary or secondary (PiP) video output*/ 00359 KEY_SRCS_WIN = 231, /* till 239 */ 00360 /* areas outside the keypad - simulated */ 00361 KEY_OUT_OF_KEYPAD = 241, 00362 KEY_REM_DPY = 242, 00363 KEY_LOC_DPY = 243, 00364 KEY_RESET = 253, /* the 'reset' keyword */ 00365 KEY_NONE = 254, /* invalid area */ 00366 KEY_DIGIT_BACKGROUND = 255, /* other areas within the keypad */ 00367 };
struct board* board_setup | ( | SDL_Surface * | screen, | |
SDL_Rect * | dest, | |||
SDL_Surface * | font, | |||
SDL_Rect * | font_rects | |||
) |
free the resources in struct gui_info and the descriptor itself. Return NULL so we can assign the value back to the descriptor in case.
Definition at line 185 of file console_gui.c.
References ast_free, display_window::bmp, delete_board(), gui_info::font, gui_info::keypad, gui_info::kp, gui_info::outfd, gui_info::win, and WIN_MAX.
00186 { 00187 int i; 00188 00189 if (gui == NULL) 00190 return NULL; 00191 00192 /* unload font file */ 00193 if (gui->font) { 00194 SDL_FreeSurface(gui->font); 00195 gui->font = NULL; 00196 } 00197 00198 if (gui->outfd > -1) 00199 close(gui->outfd); 00200 if (gui->keypad) 00201 SDL_FreeSurface(gui->keypad); 00202 gui->keypad = NULL; 00203 if (gui->kp) 00204 ast_free(gui->kp); 00205 00206 /* uninitialize the SDL environment */ 00207 for (i = 0; i < WIN_MAX; i++) { 00208 if (gui->win[i].bmp) 00209 SDL_FreeYUVOverlay(gui->win[i].bmp); 00210 } 00211 memset(gui, '\0', sizeof(gui)); 00212 00213 /* deallocates the space allocated for the keypad message boards */ 00214 if (gui->bd_dialed) 00215 delete_board(gui->bd_dialed); 00216 if (gui->bd_msg) 00217 delete_board(gui->bd_msg); 00218 00219 /* deallocates the space allocated for the thumbnail message boards */ 00220 for (i = 0; i < device_num; i++) { 00221 if (gui->thumb_bd_array[i].board) /* may be useless */ 00222 delete_board(gui->thumb_bd_array[i].board); 00223 } 00224 00225 ast_free(gui); 00226 SDL_Quit(); 00227 return NULL; 00228 }
int compute_drag | ( | int * | start, | |
int | end, | |||
int | magnifier | |||
) |
Definition at line 905 of file console_gui.c.
References POLARITY.
Referenced by eventhandler().
00906 { 00907 int delta = end - *start; 00908 #define POLARITY -1 00909 /* add a small quadratic term */ 00910 delta += delta * delta * (delta > 0 ? 1 : -1 )/100; 00911 delta *= POLARITY * magnifier; 00912 #undef POLARITY 00913 *start = end; 00914 return delta; 00915 }
char* console_do_answer | ( | int | fd | ) |
static void eventhandler | ( | struct video_desc * | env, | |
const char * | caption | |||
) | [static] |
refresh the screen, and also grab a bunch of events.
Definition at line 953 of file console_gui.c.
References ast_cli_command, ast_log(), gui_info::bd_msg, compute_drag(), gui_info::drag, DRAG_LOCAL, DRAG_MESSAGE, DRAG_NONE, DRAG_PIP, drag_info::drag_window, grabber_move(), handle_keyboard_input(), handle_mousedown(), LOG_WARNING, move_message_board(), N_EVENTS, gui_info::outfd, pip_move(), type, drag_info::x_start, and drag_info::y_start.
00954 { 00955 struct gui_info *gui = env->gui; 00956 struct drag_info *drag; 00957 #define N_EVENTS 32 00958 int i, n; 00959 SDL_Event ev[N_EVENTS]; 00960 00961 if (!gui) 00962 return; 00963 drag = &gui->drag; 00964 if (caption) 00965 SDL_WM_SetCaption(caption, NULL); 00966 00967 #define MY_EV (SDL_MOUSEBUTTONDOWN|SDL_KEYDOWN) 00968 while ( (n = SDL_PeepEvents(ev, N_EVENTS, SDL_GETEVENT, SDL_ALLEVENTS)) > 0) { 00969 for (i = 0; i < n; i++) { 00970 #if 0 00971 ast_log(LOG_WARNING, "------ event %d at %d %d\n", 00972 ev[i].type, ev[i].button.x, ev[i].button.y); 00973 #endif 00974 switch (ev[i].type) { 00975 default: 00976 ast_log(LOG_WARNING, "------ event %d at %d %d\n", 00977 ev[i].type, ev[i].button.x, ev[i].button.y); 00978 break; 00979 00980 case SDL_ACTIVEEVENT: 00981 #if 0 /* do not react, we don't want to die because the window is minimized */ 00982 if (ev[i].active.gain == 0 && ev[i].active.state & SDL_APPACTIVE) { 00983 ast_log(LOG_WARNING, "/* somebody has killed us ? */\n"); 00984 ast_cli_command(gui->outfd, "stop now"); 00985 } 00986 #endif 00987 break; 00988 00989 case SDL_KEYUP: /* ignore, for the time being */ 00990 break; 00991 00992 case SDL_KEYDOWN: 00993 handle_keyboard_input(env, &ev[i].key.keysym); 00994 break; 00995 00996 case SDL_MOUSEMOTION: 00997 case SDL_MOUSEBUTTONUP: 00998 if (drag->drag_window == DRAG_LOCAL && env->out.device_num) { 00999 /* move the capture source */ 01000 int dx = compute_drag(&drag->x_start, ev[i].motion.x, 3); 01001 int dy = compute_drag(&drag->y_start, ev[i].motion.y, 3); 01002 grabber_move(&env->out.devices[env->out.device_primary], dx, dy); 01003 } else if (drag->drag_window == DRAG_PIP) { 01004 /* move the PiP image inside the frames of the enc_in buffers */ 01005 int dx = ev[i].motion.x - drag->x_start; 01006 int dy = ev[i].motion.y - drag->y_start; 01007 /* dx and dy value are directly applied to env->out.pip_x and 01008 env->out.pip_y, so they must work as if the format was cif */ 01009 dx = (double)dx*env->enc_in.w/env->loc_dpy.w; 01010 dy = (double)dy*env->enc_in.h/env->loc_dpy.h; 01011 /* sets starts to a new value */ 01012 drag->x_start = ev[i].motion.x; 01013 drag->y_start = ev[i].motion.y; 01014 /* ast_log(LOG_WARNING, "moving: %d, %d\n", dx, dy); */ 01015 pip_move(env, dx, dy); 01016 } else if (drag->drag_window == DRAG_MESSAGE) { 01017 /* scroll up/down the window */ 01018 int dy = compute_drag(&drag->y_start, ev[i].motion.y, 1); 01019 move_message_board(gui->bd_msg, dy); 01020 } 01021 if (ev[i].type == SDL_MOUSEBUTTONUP) 01022 drag->drag_window = DRAG_NONE; 01023 break; 01024 case SDL_MOUSEBUTTONDOWN: 01025 handle_mousedown(env, ev[i].button); 01026 break; 01027 } 01028 } 01029 } 01030 if (1) { 01031 struct timeval b, a = ast_tvnow(); 01032 int i; 01033 //SDL_Lock_EventThread(); 01034 SDL_PumpEvents(); 01035 b = ast_tvnow(); 01036 i = ast_tvdiff_ms(b, a); 01037 if (i > 3) 01038 fprintf(stderr, "-------- SDL_PumpEvents took %dms\n", i); 01039 //SDL_Unlock_EventThread(); 01040 } 01041 }
static void grabber_move | ( | struct video_device * | , | |
int | dx, | |||
int | dy | |||
) | [static] |
Referenced by eventhandler().
static struct gui_info* gui_init | ( | const char * | keypad_file, | |
const char * | font | |||
) | [static] |
Definition at line 1062 of file console_gui.c.
References ast_calloc, ast_free, ast_log(), ast_strlen_zero(), DRAG_NONE, FONT_H, FONT_W, keypad_setup(), KO_MESSAGE, load_image(), and LOG_WARNING.
Referenced by sdl_setup().
01063 { 01064 struct gui_info *gui = ast_calloc(1, sizeof(*gui)); 01065 01066 if (gui == NULL) 01067 return NULL; 01068 /* initialize keypad status */ 01069 gui->kb_output = KO_MESSAGE; /* XXX temp */ 01070 gui->drag.drag_window = DRAG_NONE; 01071 gui->outfd = -1; 01072 01073 keypad_setup(gui, keypad_file); 01074 if (gui->keypad == NULL) /* no keypad, we are done */ 01075 return gui; 01076 /* XXX load image */ 01077 if (!ast_strlen_zero(font)) { 01078 int i; 01079 SDL_Rect *r; 01080 01081 gui->font = load_image(font); 01082 if (!gui->font) { 01083 ast_log(LOG_WARNING, "Unable to load font %s, no output available\n", font); 01084 goto error; 01085 } 01086 ast_log(LOG_WARNING, "Loaded font %s\n", font); 01087 /* XXX hardwired constants - 3 rows of 32 chars */ 01088 r = gui->font_rects; 01089 #define FONT_H 20 01090 #define FONT_W 9 01091 for (i = 0; i < 96; r++, i++) { 01092 r->x = (i % 32 ) * FONT_W; 01093 r->y = (i / 32 ) * FONT_H; 01094 r->w = FONT_W; 01095 r->h = FONT_H; 01096 } 01097 } 01098 01099 gui->outfd = open ("/dev/null", O_WRONLY); /* discard output, temporary */ 01100 if (gui->outfd < 0) { 01101 ast_log(LOG_WARNING, "Unable output fd\n"); 01102 goto error; 01103 } 01104 return gui; 01105 01106 error: 01107 ast_free(gui); 01108 return NULL; 01109 }
static int gui_map_token | ( | const char * | s | ) | [static] |
Definition at line 1536 of file console_gui.c.
References gui_key_map, _s_k::k, KEY_NONE, and _s_k::s.
Referenced by keypad_cfg_read().
01537 { 01538 /* map the string into token to be returned */ 01539 int i = atoi(s); 01540 struct _s_k *p; 01541 if (i > 0 || s[1] == '\0') /* numbers or single characters */ 01542 return (i > 9) ? i : s[0]; 01543 for (p = gui_key_map; p->s; p++) { 01544 if (!strcasecmp(p->s, s)) 01545 return p->k; 01546 } 01547 return KEY_NONE; /* not found */ 01548 }
static void handle_keyboard_input | ( | struct video_desc * | env, | |
SDL_keysym * | ks | |||
) | [static] |
Definition at line 875 of file console_gui.c.
References gui_info::bd_msg, gui_info::kb_output, keypad_pick_up(), KO_DIALED, KO_INPUT, KO_MESSAGE, map_key(), and print_message().
Referenced by eventhandler().
00876 { 00877 char buf[2] = { map_key(ks), '\0' }; 00878 struct gui_info *gui = env->gui; 00879 if (buf[0] == 0) /* modifier ? */ 00880 return; 00881 switch (gui->kb_output) { 00882 default: 00883 break; 00884 case KO_INPUT: /* to be completed */ 00885 break; 00886 case KO_MESSAGE: 00887 if (gui->bd_msg) { 00888 print_message(gui->bd_msg, buf); 00889 if (buf[0] == '\r' || buf[0] == '\n') { 00890 keypad_pick_up(env); 00891 } 00892 } 00893 break; 00894 00895 case KO_DIALED: /* to be completed */ 00896 break; 00897 } 00898 00899 return; 00900 }
static void handle_mousedown | ( | struct video_desc * | env, | |
SDL_MouseButtonEvent | button | |||
) | [static] |
Definition at line 619 of file console_gui.c.
References ast_log(), BORDER, keypad_entry::c, gui_info::drag, DRAG_NONE, drag_info::drag_window, KEY_LOC_DPY, KEY_OUT_OF_KEYPAD, KEY_REM_DPY, gui_info::keypad, gui_info::kp, kp_match_area(), gui_info::kp_size, gui_info::kp_used, LOG_WARNING, MAX, SRC_MSG_BD_H, SRC_WIN_H, and SRC_WIN_W.
Referenced by eventhandler().
00620 { 00621 uint8_t index = KEY_OUT_OF_KEYPAD; /* the key or region of the display we clicked on */ 00622 struct gui_info *gui = env->gui; 00623 00624 int i; /* integer variable used as iterator */ 00625 00626 int x; /* integer variable usable as a container */ 00627 00628 /* total width of source device thumbnails */ 00629 int src_wins_tot_w = env->out.device_num*(SRC_WIN_W+BORDER)+BORDER; 00630 00631 /* x coordinate of the center of the keypad */ 00632 int x0 = MAX(env->rem_dpy.w+gui->keypad->w/2+2*BORDER, src_wins_tot_w/2); 00633 00634 #if 0 00635 ast_log(LOG_WARNING, "event %d %d have %d/%d regions at %p\n", 00636 button.x, button.y, gui->kp_used, gui->kp_size, gui->kp); 00637 #endif 00638 /* for each mousedown we end previous drag */ 00639 gui->drag.drag_window = DRAG_NONE; 00640 00641 /* define keypad boundary */ 00642 /* XXX this should be extended for clicks on different audio device markers */ 00643 if (button.y >= (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0)) { 00644 /* if control reaches this point this means that the clicked point is 00645 below the row of the additional sources windows*/ 00646 /* adjust the y coordinate as if additional devices windows were not present */ 00647 button.y -= (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0); 00648 if (button.y < BORDER) 00649 index = KEY_OUT_OF_KEYPAD; 00650 else if (button.y >= MAX(MAX(env->rem_dpy.h, env->loc_dpy.h), gui->keypad->h)) 00651 index = KEY_OUT_OF_KEYPAD; 00652 else if (button.x < x0 - gui->keypad->w/2 - BORDER - env->rem_dpy.w) 00653 index = KEY_OUT_OF_KEYPAD; 00654 else if (button.x < x0 - gui->keypad->w/2 - BORDER) 00655 index = KEY_REM_DPY; 00656 else if (button.x < x0 - gui->keypad->w/2) 00657 index = KEY_OUT_OF_KEYPAD; 00658 else if (button.x >= x0 + gui->keypad->w/2 + BORDER + env->loc_dpy.w) 00659 index = KEY_OUT_OF_KEYPAD; 00660 else if (button.x >= x0 + gui->keypad->w/2 + BORDER) 00661 index = KEY_LOC_DPY; 00662 else if (button.x >= x0 + gui->keypad->w/2) 00663 index = KEY_OUT_OF_KEYPAD; 00664 else if (gui->kp) { 00665 /* we have to calculate the first coordinate 00666 inside the keypad before calling the kp_match_area*/ 00667 int x_keypad = button.x - (x0 - gui->keypad->w/2); 00668 /* find the key clicked (if one was clicked) */ 00669 for (i = 0; i < gui->kp_used; i++) { 00670 if (kp_match_area(&gui->kp[i],x_keypad, button.y - BORDER)) { 00671 index = gui->kp[i].c; 00672 break; 00673 } 00674 } 00675 } 00676 } else if (button.y < BORDER) { 00677 index = KEY_OUT_OF_KEYPAD; 00678 } else { /* we are in the thumbnail area */ 00679 x = x0 - src_wins_tot_w/2 + BORDER; 00680 if (button.y >= BORDER + SRC_WIN_H) 00681 index = KEY_OUT_OF_KEYPAD; 00682 else if (button.x < x) 00683 index = KEY_OUT_OF_KEYPAD; 00684 else if (button.x < x + src_wins_tot_w - BORDER) { 00685 /* note that the additional device windows 00686 are numbered from left to right 00687 starting from 0, with a maximum of 8, the index associated on a click is: 00688 KEY_SRCS_WIN + number_of_the_window */ 00689 for (i = 1; i <= env->out.device_num; i++) { 00690 if (button.x < x+i*(SRC_WIN_W+BORDER)-BORDER) { 00691 index = KEY_SRCS_WIN+i-1; 00692 break; 00693 } else if (button.x < x+i*(SRC_WIN_W+BORDER)) { 00694 index = KEY_OUT_OF_KEYPAD; 00695 break; 00696 } 00697 } 00698 } else 00699 index = KEY_OUT_OF_KEYPAD; 00700 } 00701 00702 /* exec the function */ 00703 if (index < 128) { /* surely clicked on the keypad, don't care which key */ 00704 keypad_digit(env, index); 00705 return; 00706 } 00707 00708 else if (index >= KEY_SRCS_WIN && index < KEY_SRCS_WIN+env->out.device_num) { 00709 index -= KEY_SRCS_WIN; /* index of the window, equal to the device index in the table */ 00710 /* if one of the additional device windows is clicked with 00711 left or right mouse button, we have to switch to that device */ 00712 if (button.button == SDL_BUTTON_RIGHT || button.button == SDL_BUTTON_LEFT) { 00713 switch_video_out(env, index, button.button); 00714 return; 00715 } 00716 /* turn on or off the devices selectively with other mouse buttons */ 00717 else { 00718 int ret = turn_on_off(index, env); 00719 /* print a message according to what happened */ 00720 if (!ret) 00721 ast_log(LOG_WARNING, "unable to turn on device %s\n", 00722 env->out.devices[index].name); 00723 else if (ret == 1) 00724 ast_log(LOG_WARNING, "device %s changed state to on\n", 00725 env->out.devices[index].name); 00726 else if (ret == 2) 00727 ast_log(LOG_WARNING, "device %s changed state to off\n", 00728 env->out.devices[index].name); 00729 return; 00730 } 00731 } 00732 00733 /* XXX for future implementation 00734 else if (click on audio source marker) 00735 change audio source device 00736 */ 00737 00738 switch (index) { 00739 /* answer/close function */ 00740 case KEY_PICK_UP: 00741 keypad_pick_up(env); 00742 break; 00743 case KEY_HANG_UP: 00744 ast_cli_command(gui->outfd, "console hangup"); 00745 break; 00746 00747 /* other functions */ 00748 case KEY_MUTE: /* send or not send the audio */ 00749 case KEY_AUTOANSWER: 00750 case KEY_SENDVIDEO: /* send or not send the video */ 00751 case KEY_PIP: /* activate/deactivate picture in picture mode */ 00752 case KEY_FREEZE: /* freeze/unfreeze the incoming video */ 00753 keypad_toggle(env, index); 00754 break; 00755 00756 case KEY_LOCALVIDEO: 00757 break; 00758 case KEY_REMOTEVIDEO: 00759 break; 00760 00761 #ifdef notyet /* XXX for future implementations */ 00762 case KEY_CAPTURE: 00763 break; 00764 #endif 00765 00766 case KEY_MESSAGEBOARD: 00767 if (button.button == SDL_BUTTON_LEFT) 00768 set_drag(&gui->drag, button.x, button.y, DRAG_MESSAGE); 00769 break; 00770 00771 /* press outside the keypad. right increases size, center decreases, left drags */ 00772 case KEY_LOC_DPY: 00773 case KEY_REM_DPY: 00774 if (button.button == SDL_BUTTON_LEFT) { 00775 /* values used to find the position of the picture in picture (if present) */ 00776 int pip_loc_x = (double)env->out.pip_x/env->enc_in.w * env->loc_dpy.w; 00777 int pip_loc_y = (double)env->out.pip_y/env->enc_in.h * env->loc_dpy.h; 00778 /* check if picture in picture is active and the click was on it */ 00779 if (index == KEY_LOC_DPY && env->out.picture_in_picture && 00780 button.x >= x0+gui->keypad->w/2+BORDER+pip_loc_x && 00781 button.x < x0+gui->keypad->w/2+BORDER+pip_loc_x+env->loc_dpy.w/3 && 00782 button.y >= BORDER+pip_loc_y && 00783 button.y < BORDER+pip_loc_y+env->loc_dpy.h/3) { 00784 /* set the y cordinate to his previous value */ 00785 button.y += (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0); 00786 /* starts dragging the picture inside the picture */ 00787 set_drag(&gui->drag, button.x, button.y, DRAG_PIP); 00788 } 00789 else if (index == KEY_LOC_DPY) { 00790 /* set the y cordinate to his previous value */ 00791 button.y += (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0); 00792 /* click in the local display, but not on the PiP */ 00793 set_drag(&gui->drag, button.x, button.y, DRAG_LOCAL); 00794 } 00795 break; 00796 } else { 00797 char buf[128]; 00798 struct fbuf_t *fb = index == KEY_LOC_DPY ? &env->loc_dpy : &env->rem_dpy; 00799 sprintf(buf, "%c%dx%d", button.button == SDL_BUTTON_RIGHT ? '>' : '<', 00800 fb->w, fb->h); 00801 video_geom(fb, buf); 00802 sdl_setup(env); 00803 /* writes messages in the source boards, those can be 00804 modified during the execution, because of the events 00805 this must be done here, otherwise the status of sources will not be 00806 shown after sdl_setup */ 00807 for (i = 0; i < env->out.device_num; i++) { 00808 update_device_info(env, i); 00809 } 00810 /* we also have to refresh other boards, 00811 to avoid messages to disappear after video resize */ 00812 print_message(gui->bd_msg, " \b"); 00813 print_message(gui->bd_dialed, " \b"); 00814 } 00815 break; 00816 case KEY_OUT_OF_KEYPAD: 00817 ast_log(LOG_WARNING, "nothing clicked, coordinates: %d, %d\n", button.x, button.y); 00818 break; 00819 00820 case KEY_DIGIT_BACKGROUND: 00821 break; 00822 00823 default: 00824 ast_log(LOG_WARNING, "function not yet defined %i\n", index); 00825 } 00826 }
static void init_board | ( | struct gui_info * | gui, | |
struct board ** | dst, | |||
SDL_Rect * | r, | |||
int | dx, | |||
int | dy | |||
) | [static] |
initialize the boards we have in the keypad
Definition at line 1186 of file console_gui.c.
References board_setup(), gui_info::font, gui_info::font_rects, and gui_info::screen.
Referenced by sdl_setup().
01187 { 01188 if (r[0].w == 0 || r[0].h == 0) 01189 return; /* not available */ 01190 r[1] = r[0]; /* copy geometry */ 01191 r[1].x += dx; /* add offset of main window */ 01192 r[1].y += dy; 01193 if (*dst == NULL) { /* initial call */ 01194 *dst = board_setup(gui->screen, &r[1], gui->font, gui->font_rects); 01195 } else { 01196 /* call a refresh */ 01197 } 01198 }
static int keypad_cfg_read | ( | struct gui_info * | gui, | |
const char * | val | |||
) | [static] |
read a keypad entry line in the format reset token circle xc yc diameter token circle xc yc x1 y1 h # ellipse, main diameter and height token rect x0 y0 x1 y1 h # rectangle with main side and eight token x0 y0 w h # horizontal rectangle (short format) # this is used e.g. for message boards token is the token to be returned, either a character or a symbol as KEY_* above Return 1 on success, 0 on error.
Definition at line 1561 of file console_gui.c.
References ast_calloc, ast_log(), ast_realloc, gui_map_token(), KEY_DIALED, KEY_EDIT, KEY_FONT, KEY_KEYPAD, KEY_MESSAGE, KEY_NONE, KEY_RESET, gui_info::kp, KP_CIRCLE, gui_info::kp_dialed, gui_info::kp_edit, gui_info::kp_msg, KP_RECT, gui_info::kp_rect, gui_info::kp_size, gui_info::kp_used, and LOG_WARNING.
Referenced by keypad_setup().
01562 { 01563 struct keypad_entry e; 01564 SDL_Rect *r = NULL; 01565 char s1[16], s2[16]; 01566 int i, ret = 0; /* default, error */ 01567 01568 if (gui == NULL || val == NULL) 01569 return 0; 01570 01571 s1[0] = s2[0] = '\0'; 01572 memset(&e, '\0', sizeof(e)); 01573 i = sscanf(val, "%14s %14s %d %d %d %d %d", 01574 s1, s2, &e.x0, &e.y0, &e.x1, &e.y1, &e.h); 01575 01576 e.c = gui_map_token(s1); 01577 if (e.c == KEY_NONE) 01578 return 0; /* nothing found */ 01579 switch (i) { 01580 default: 01581 break; 01582 case 1: /* only "reset" is allowed */ 01583 if (e.c != KEY_RESET) 01584 break; 01585 if (gui->kp) 01586 gui->kp_used = 0; 01587 break; 01588 case 5: 01589 if (e.c == KEY_KEYPAD) /* active keypad area */ 01590 r = &gui->kp_rect; 01591 else if (e.c == KEY_MESSAGE) 01592 r = gui->kp_msg; 01593 else if (e.c == KEY_DIALED) 01594 r = gui->kp_dialed; 01595 else if (e.c == KEY_EDIT) 01596 r = gui->kp_edit; 01597 if (r) { 01598 r->x = atoi(s2); /* this becomes x0 */ 01599 r->y = e.x0; /* this becomes y0 */ 01600 r->w = e.y0; /* this becomes w */ 01601 r->h = e.x1; /* this becomes h */ 01602 break; 01603 } 01604 if (strcasecmp(s2, "circle")) /* invalid */ 01605 break; 01606 /* token circle xc yc diameter */ 01607 e.h = e.x1; 01608 e.y1 = e.y0; /* map radius in x1 y1 */ 01609 e.x1 = e.x0 + e.h; /* map radius in x1 y1 */ 01610 e.x0 = e.x0 - e.h; /* map radius in x1 y1 */ 01611 /* fallthrough */ 01612 01613 case 7: 01614 if (e.c == KEY_FONT) { /* font - x0 y0 w h rows cols */ 01615 ast_log(LOG_WARNING, "font not supported yet\n"); 01616 break; 01617 } 01618 /* token circle|rect x0 y0 x1 y1 h */ 01619 if (e.x1 < e.x0 || e.h <= 0) { 01620 ast_log(LOG_WARNING, "error in coordinates\n"); 01621 e.type = 0; 01622 break; 01623 } 01624 if (!strcasecmp(s2, "circle")) { 01625 /* for a circle we specify the diameter but store center and radii */ 01626 e.type = KP_CIRCLE; 01627 e.x0 = (e.x1 + e.x0) / 2; 01628 e.y0 = (e.y1 + e.y0) / 2; 01629 e.h = e.h / 2; 01630 } else if (!strcasecmp(s2, "rect")) { 01631 e.type = KP_RECT; 01632 } else 01633 break; 01634 ret = 1; 01635 } 01636 // ast_log(LOG_WARNING, "reading [%s] returns %d %d\n", val, i, ret); 01637 if (ret == 0) 01638 return 0; 01639 if (gui->kp_size == 0) { 01640 gui->kp = ast_calloc(10, sizeof(e)); 01641 if (gui->kp == NULL) { 01642 ast_log(LOG_WARNING, "cannot allocate kp\n"); 01643 return 0; 01644 } 01645 gui->kp_size = 10; 01646 } 01647 if (gui->kp_size == gui->kp_used) { /* must allocate */ 01648 struct keypad_entry *a = ast_realloc(gui->kp, sizeof(e)*(gui->kp_size+10)); 01649 if (a == NULL) { 01650 ast_log(LOG_WARNING, "cannot reallocate kp\n"); 01651 return 0; 01652 } 01653 gui->kp = a; 01654 gui->kp_size += 10; 01655 } 01656 if (gui->kp_size == gui->kp_used) 01657 return 0; 01658 gui->kp[gui->kp_used++] = e; 01659 // ast_log(LOG_WARNING, "now %d regions\n", gui->kp_used); 01660 return 1; 01661 }
static void keypad_digit | ( | struct video_desc * | env, | |
int | digit | |||
) | [static] |
Definition at line 374 of file console_gui.c.
References AST_FRAME_DTMF, ast_queue_frame(), f, and print_message().
00375 { 00376 if (env->owner) { /* we have a call, send the digit */ 00377 struct ast_frame f = { AST_FRAME_DTMF, 0 }; 00378 00379 f.subclass = digit; 00380 ast_queue_frame(env->owner, &f); 00381 } else { /* no call, accumulate digits */ 00382 char buf[2] = { digit, '\0' }; 00383 if (env->gui->bd_msg) /* XXX not strictly necessary ... */ 00384 print_message(env->gui->bd_msg, buf); 00385 } 00386 }
static void keypad_pick_up | ( | struct video_desc * | env | ) | [static] |
Definition at line 432 of file console_gui.c.
References ast_cli_command, ast_log(), ast_skip_blanks(), gui_info::bd_dialed, gui_info::bd_msg, LOG_WARNING, gui_info::outfd, print_message(), read_message(), and reset_board().
Referenced by handle_keyboard_input().
00433 { 00434 struct gui_info *gui = env->gui; 00435 00436 ast_log(LOG_WARNING, "keypad_pick_up called\n"); 00437 00438 if (env->owner) { /* someone is calling us, just answer */ 00439 ast_cli_command(gui->outfd, "console answer"); 00440 } else { /* we have someone to call */ 00441 char buf[160]; 00442 const char *who = ast_skip_blanks(read_message(gui->bd_msg)); 00443 buf[sizeof(buf) - 1] = '\0'; 00444 snprintf(buf, sizeof(buf), "console dial %s", who); 00445 ast_log(LOG_WARNING, "doing <%s>\n", buf); 00446 print_message(gui->bd_dialed, "\n"); 00447 print_message(gui->bd_dialed, who); 00448 reset_board(gui->bd_msg); 00449 ast_cli_command(gui->outfd, buf); 00450 } 00451 }
static void keypad_setup | ( | struct gui_info * | gui, | |
const char * | kp_file | |||
) | [static] |
Definition at line 1127 of file console_gui.c.
References ast_log(), ast_skip_blanks(), ast_trim_blanks(), gui_info::keypad, keypad_cfg_read(), load_image(), and LOG_WARNING.
Referenced by gui_init().
01128 { 01129 FILE *fd; 01130 char buf[1024]; 01131 const char region[] = "region"; 01132 int reg_len = strlen(region); 01133 int in_comment = 0; 01134 01135 if (gui->keypad) 01136 return; 01137 gui->keypad = load_image(kp_file); 01138 if (!gui->keypad) 01139 return; 01140 /* now try to read the keymap from the file. */ 01141 fd = fopen(kp_file, "r"); 01142 if (fd == NULL) { 01143 ast_log(LOG_WARNING, "fail to open %s\n", kp_file); 01144 return; 01145 } 01146 /* 01147 * If the keypad image has a comment field, try to read 01148 * the button location from there. The block must start with 01149 * a comment (or empty) line, and continue with entries like: 01150 * region = token shape x0 y0 x1 y1 h 01151 * ... 01152 * (basically, lines have the same format as config file entries). 01153 * You can add it to a jpeg file using wrjpgcom 01154 */ 01155 while (fgets(buf, sizeof(buf), fd)) { 01156 char *s; 01157 01158 if (!strstr(buf, region)) { /* no keyword yet */ 01159 if (!in_comment) /* still waiting for initial comment block */ 01160 continue; 01161 else 01162 break; 01163 } 01164 if (!in_comment) { /* first keyword, reset previous entries */ 01165 keypad_cfg_read(gui, "reset"); 01166 in_comment = 1; 01167 } 01168 s = ast_skip_blanks(buf); 01169 ast_trim_blanks(s); 01170 if (memcmp(s, region, reg_len)) 01171 break; /* keyword not found */ 01172 s = ast_skip_blanks(s + reg_len); /* space between token and '=' */ 01173 if (*s++ != '=') /* missing separator */ 01174 break; 01175 if (*s == '>') /* skip '>' if present */ 01176 s++; 01177 keypad_cfg_read(gui, ast_skip_blanks(s)); 01178 } 01179 fclose(fd); 01180 }
static char* keypad_toggle | ( | struct video_desc * | env, | |
int | index | |||
) | [static] |
Definition at line 389 of file console_gui.c.
References ast_cli_command, ast_log(), chan_oss_pvt::autoanswer, find_desc(), KEY_AUTOANSWER, KEY_FREEZE, KEY_MUTE, KEY_PIP, KEY_SENDVIDEO, LOG_WARNING, and oss_active.
00390 { 00391 ast_log(LOG_WARNING, "keypad_toggle(%i) called\n", index); 00392 00393 switch (index) { 00394 case KEY_SENDVIDEO: /* send or do not send video */ 00395 env->out.sendvideo = !env->out.sendvideo; 00396 break; 00397 00398 case KEY_PIP: /* enable or disable Picture in Picture */ 00399 env->out.picture_in_picture = !env->out.picture_in_picture; 00400 break; 00401 00402 case KEY_MUTE: /* send or do not send audio */ 00403 ast_cli_command(env->gui->outfd, "console mute toggle"); 00404 break; 00405 00406 case KEY_FREEZE: /* freeze/unfreeze the incoming frames */ 00407 env->frame_freeze = !env->frame_freeze; 00408 break; 00409 00410 #ifdef notyet 00411 case KEY_AUTOANSWER: { 00412 struct chan_oss_pvt *o = find_desc(oss_active); 00413 o->autoanswer = !o->autoanswer; 00414 } 00415 break; 00416 #endif 00417 } 00418 return NULL; 00419 }
static int kp_match_area | ( | const struct keypad_entry * | e, | |
int | x, | |||
int | y | |||
) | [static] |
Definition at line 1487 of file console_gui.c.
References ast_log(), keypad_entry::c, keypad_entry::h, KP_CIRCLE, KP_RECT, LOG_WARNING, keypad_entry::type, keypad_entry::x0, keypad_entry::x1, keypad_entry::y0, and keypad_entry::y1.
Referenced by handle_mousedown().
01488 { 01489 double xp, dx = (e->x1 - e->x0); 01490 double yp, dy = (e->y1 - e->y0); 01491 double l = sqrt(dx*dx + dy*dy); 01492 int ret = 0; 01493 01494 if (l > 1) { /* large enough */ 01495 xp = ((x - e->x0)*dx + (y - e->y0)*dy)/l; 01496 yp = (-(x - e->x0)*dy + (y - e->y0)*dx)/l; 01497 if (e->type == KP_RECT) { 01498 ret = (xp >= 0 && xp < l && yp >=0 && yp < e->h); 01499 } else if (e->type == KP_CIRCLE) { 01500 dx = xp*xp/(l*l) + yp*yp/(e->h*e->h); 01501 ret = (dx < 1); 01502 } 01503 } 01504 #if 0 01505 ast_log(LOG_WARNING, "result %d [%d] for match %d,%d in type %d p0 %d,%d p1 %d,%d h %d\n", 01506 ret, e->c, x, y, e->type, e->x0, e->y0, e->x1, e->y1, e->h); 01507 #endif 01508 return ret; 01509 }
static SDL_Surface* load_image | ( | const char * | file | ) | [static] |
Definition at line 1043 of file console_gui.c.
Referenced by gui_init(), and keypad_setup().
01044 { 01045 SDL_Surface *temp; 01046 01047 #ifdef HAVE_SDL_IMAGE 01048 temp = IMG_Load(file); 01049 #else 01050 temp = SDL_LoadBMP(file); 01051 #endif 01052 if (temp == NULL) 01053 fprintf(stderr, "Unable to load image %s: %s\n", 01054 file, SDL_GetError()); 01055 return temp; 01056 }
static char map_key | ( | SDL_keysym * | ks | ) | [static] |
Definition at line 847 of file console_gui.c.
Referenced by handle_keyboard_input().
00848 { 00849 const char *s, **p = us_kbd_map; 00850 int c = ks->sym; 00851 00852 if (c == '\r') /* map cr into lf */ 00853 c = '\n'; 00854 if (c >= SDLK_NUMLOCK && c <= SDLK_COMPOSE) 00855 return 0; /* only a modifier */ 00856 if (ks->mod == 0) 00857 return c; 00858 while ((s = *p) && s[0] != c) 00859 p++; 00860 if (s) { /* see if we have a modifier and a chance to use it */ 00861 int l = strlen(s), mod = 0; 00862 if (l > 1) 00863 mod |= (ks->mod & KMOD_SHIFT) ? 1 : 0; 00864 if (l > 2 + mod) 00865 mod |= (ks->mod & KMOD_CTRL) ? 2 : 0; 00866 if (l > 4 + mod) 00867 mod |= (ks->mod & KMOD_ALT) ? 4 : 0; 00868 c = s[mod]; 00869 } 00870 if (ks->mod & (KMOD_CAPS|KMOD_SHIFT) && c >= 'a' && c <='z') 00871 c += 'A' - 'a'; 00872 return c; 00873 }
static int my_x_handler | ( | Display * | d, | |
XErrorEvent * | e | |||
) | [static] |
Definition at line 1208 of file console_gui.c.
References ast_log(), and LOG_WARNING.
Referenced by sdl_setup().
01209 { 01210 ast_log(LOG_WARNING, "%s error_code %d\n", __FUNCTION__, e->error_code); 01211 return 0; 01212 }
static void pip_move | ( | struct video_desc * | env, | |
int | dx, | |||
int | dy | |||
) | [static] |
This function moves the picture in picture, controlling the limits of the containing buffer to avoid problems deriving from going through the limits.
env | = pointer to the descriptor of the video environment | |
dx | = the variation of the x position | |
dy | = the variation of the y position |
Definition at line 925 of file console_gui.c.
Referenced by eventhandler().
00925 { 00926 int new_pip_x = env->out.pip_x+dx; 00927 int new_pip_y = env->out.pip_y+dy; 00928 /* going beyond the left borders */ 00929 if (new_pip_x < 0) 00930 new_pip_x = 0; 00931 /* going beyond the right borders */ 00932 else if (new_pip_x > env->enc_in.w - env->enc_in.w/3) 00933 new_pip_x = env->enc_in.w - env->enc_in.w/3; 00934 /* going beyond the top borders */ 00935 if (new_pip_y < 0) 00936 new_pip_y = 0; 00937 /* going beyond the bottom borders */ 00938 else if (new_pip_y > env->enc_in.h - env->enc_in.h/3) 00939 new_pip_y = env->enc_in.h - env->enc_in.h/3; 00940 env->out.pip_x = new_pip_x; 00941 env->out.pip_y = new_pip_y; 00942 }
static void sdl_setup | ( | struct video_desc * | env | ) | [static] |
[re]set the main sdl window, useful in case of resize. We can tell the first from subsequent calls from the value of env->gui, which is NULL the first time.
Definition at line 1219 of file console_gui.c.
References ast_log(), ast_strlen_zero(), gui_info::bd_msg, board_setup(), BORDER, gui_info::font, gui_info::font_rects, gui_init(), init_board(), gui_info::keypad, gui_info::kp_rect, LOG_ERROR, LOG_WARNING, MAX, my_x_handler(), thumb_bd::rect, gui_info::screen, set_win(), SRC_MSG_BD_H, SRC_WIN_H, SRC_WIN_W, gui_info::thumb_bd_array, gui_info::win, WIN_KEYPAD, WIN_LOCAL, WIN_REMOTE, and WIN_SRC1.
01220 { 01221 int dpy_fmt = SDL_IYUV_OVERLAY; /* YV12 causes flicker in SDL */ 01222 int depth, maxw, maxh; 01223 const SDL_VideoInfo *info; 01224 int kp_w = 0, kp_h = 0; /* keypad width and height */ 01225 struct gui_info *gui = env->gui; 01226 01227 /* Some helper variables used for filling the SDL window */ 01228 int x0; /* the x coordinate of the center of the keypad */ 01229 int x1; /* userful for calculating of the size of the parent window */ 01230 int y0; /* y coordinate of the keypad, the remote window and the local window */ 01231 int src_wins_tot_w; /* total width of the source windows */ 01232 int i; 01233 int x; /* useful for the creation of the source windows; */ 01234 01235 #ifdef HAVE_X11 01236 const char *e = getenv("SDL_WINDOWID"); 01237 01238 if (!ast_strlen_zero(e)) { 01239 XWindowAttributes a; 01240 int (*old_x_handler)(Display *d, XErrorEvent *e) = XSetErrorHandler(my_x_handler); 01241 Display *d = XOpenDisplay(getenv("DISPLAY")); 01242 long w = atol(e); 01243 int success = w ? XGetWindowAttributes(d, w, &a) : 0; 01244 01245 XSetErrorHandler(old_x_handler); 01246 if (!success) { 01247 ast_log(LOG_WARNING, "%s error in window\n", __FUNCTION__); 01248 return; 01249 } 01250 } 01251 #endif 01252 /* 01253 * initialize the SDL environment. We have one large window 01254 * with local and remote video, and a keypad. 01255 * At the moment we arrange them statically, as follows: 01256 * - top row: thumbnails for local video sources; 01257 * - next row: message boards for local video sources 01258 * - on the left, the remote video; 01259 * - on the center, the keypad 01260 * - on the right, the local video 01261 * We need to read in the skin for the keypad before creating the main 01262 * SDL window, because the size is only known here. 01263 */ 01264 01265 if (gui == NULL && SDL_Init(SDL_INIT_VIDEO)) { 01266 ast_log(LOG_WARNING, "Could not initialize SDL - %s\n", 01267 SDL_GetError()); 01268 /* again not fatal, just we won't display anything */ 01269 return; 01270 } 01271 info = SDL_GetVideoInfo(); 01272 /* We want at least 16bpp to support YUV overlays. 01273 * E.g with SDL_VIDEODRIVER = aalib the default is 8 01274 */ 01275 if (!info || !info->vfmt) { 01276 ast_log(LOG_WARNING, "Bad SDL_GetVideoInfo - %s\n", 01277 SDL_GetError()); 01278 return; 01279 } 01280 depth = info->vfmt->BitsPerPixel; 01281 if (depth < 16) 01282 depth = 16; 01283 if (!gui) 01284 env->gui = gui = gui_init(env->keypad_file, env->keypad_font); 01285 if (!gui) 01286 goto no_sdl; 01287 01288 if (gui->keypad) { 01289 if (gui->kp_rect.w > 0 && gui->kp_rect.h > 0) { 01290 kp_w = gui->kp_rect.w; 01291 kp_h = gui->kp_rect.h; 01292 } else { 01293 kp_w = gui->keypad->w; 01294 kp_h = gui->keypad->h; 01295 } 01296 } 01297 01298 /* total width of the thumbnails */ 01299 src_wins_tot_w = env->out.device_num*(SRC_WIN_W+BORDER)+BORDER; 01300 01301 /* x coordinate of the center of the keypad */ 01302 x0 = MAX(env->rem_dpy.w+kp_w/2+2*BORDER, src_wins_tot_w/2); 01303 01304 /* from center of the keypad to right border */ 01305 x1 = MAX(env->loc_dpy.w+kp_w/2+2*BORDER, src_wins_tot_w/2); 01306 01307 /* total width of the SDL window to create */ 01308 maxw = x0+x1; 01309 01310 /* total height of the mother window to create */ 01311 maxh = MAX( MAX(env->rem_dpy.h, env->loc_dpy.h), kp_h)+2*BORDER; 01312 maxh += env->out.device_num ? (2*BORDER+SRC_WIN_H+SRC_MSG_BD_H) : 0; 01313 01314 gui->screen = SDL_SetVideoMode(maxw, maxh, depth, 0); 01315 if (!gui->screen) { 01316 ast_log(LOG_ERROR, "SDL: could not set video mode - exiting\n"); 01317 goto no_sdl; 01318 } 01319 01320 #ifdef HAVE_X11 01321 /* 01322 * Annoying as it may be, if SDL_WINDOWID is set, SDL does 01323 * not grab keyboard/mouse events or expose or other stuff, 01324 * and it does not handle resize either. 01325 * So we need to implement workarounds here. 01326 */ 01327 do { 01328 /* First, handle the event mask */ 01329 XWindowAttributes attr; 01330 long want; 01331 SDL_SysWMinfo info; 01332 Display *SDL_Display; 01333 Window win; 01334 01335 const char *e = getenv("SDL_WINDOWID"); 01336 if (ast_strlen_zero(e)) /* no external window, don't bother doing this */ 01337 break; 01338 SDL_VERSION(&info.version); /* it is important to set the version */ 01339 if (SDL_GetWMInfo(&info) != 1) { 01340 fprintf(stderr, "no wm info\n"); 01341 break; 01342 } 01343 SDL_Display = info.info.x11.display; 01344 if (SDL_Display == NULL) 01345 break; 01346 win = info.info.x11.window; 01347 01348 /* 01349 * A list of events we want. 01350 * Leave ResizeRedirectMask to the parent. 01351 */ 01352 want = KeyPressMask | KeyReleaseMask | ButtonPressMask | 01353 ButtonReleaseMask | EnterWindowMask | 01354 LeaveWindowMask | PointerMotionMask | 01355 Button1MotionMask | 01356 Button2MotionMask | Button3MotionMask | 01357 Button4MotionMask | Button5MotionMask | 01358 ButtonMotionMask | KeymapStateMask | 01359 ExposureMask | VisibilityChangeMask | 01360 StructureNotifyMask | /* ResizeRedirectMask | */ 01361 SubstructureNotifyMask | SubstructureRedirectMask | 01362 FocusChangeMask | PropertyChangeMask | 01363 ColormapChangeMask | OwnerGrabButtonMask; 01364 01365 memset(&attr, '\0', sizeof(attr)); 01366 XGetWindowAttributes(SDL_Display, win, &attr); 01367 01368 /* the following events can be delivered only to one client. 01369 * So check which ones are going to someone else, and drop 01370 * them from our request. 01371 */ 01372 { 01373 /* ev are the events for a single recipient */ 01374 long ev = ButtonPressMask | ResizeRedirectMask | 01375 SubstructureRedirectMask; 01376 ev &= (attr.all_event_masks & ~attr.your_event_mask); 01377 /* now ev contains 1 for single-recipient events owned by others. 01378 * We must clear those bits in 'want' 01379 * and then add the bits in 'attr.your_event_mask' to 'want' 01380 */ 01381 want &= ~ev; 01382 want |= attr.your_event_mask; 01383 } 01384 XSelectInput(SDL_Display, win, want); 01385 01386 /* Second, handle resize. 01387 * We do part of the things that X11Resize does, 01388 * but also generate a ConfigureNotify event so 01389 * the owner of the window has a chance to do something 01390 * with it. 01391 */ 01392 XResizeWindow(SDL_Display, win, maxw, maxh); 01393 { 01394 XConfigureEvent ce = { 01395 .type = ConfigureNotify, 01396 .serial = 0, 01397 .send_event = 1, /* TRUE */ 01398 .display = SDL_Display, 01399 .event = win, 01400 .window = win, 01401 .x = 0, 01402 .y = 0, 01403 .width = maxw, 01404 .height = maxh, 01405 .border_width = 0, 01406 .above = 0, 01407 .override_redirect = 0 }; 01408 XSendEvent(SDL_Display, win, 1 /* TRUE */, StructureNotifyMask, (XEvent *)&ce); 01409 } 01410 } while (0); 01411 #endif /* HAVE_X11 */ 01412 01413 y0 = env->out.device_num ? (3*BORDER+SRC_WIN_H+SRC_MSG_BD_H) : BORDER; 01414 01415 SDL_WM_SetCaption("Asterisk console Video Output", NULL); 01416 01417 /* intialize the windows for local and remote video */ 01418 if (set_win(gui->screen, &gui->win[WIN_REMOTE], dpy_fmt, 01419 env->rem_dpy.w, env->rem_dpy.h, x0-kp_w/2-BORDER-env->rem_dpy.w, y0)) 01420 goto no_sdl; 01421 /* unfreeze incoming frames if set (to avoid showing nothing) */ 01422 env->frame_freeze = 0; 01423 01424 if (set_win(gui->screen, &gui->win[WIN_LOCAL], dpy_fmt, 01425 env->loc_dpy.w, env->loc_dpy.h, 01426 x0+kp_w/2+BORDER, y0)) 01427 goto no_sdl; 01428 01429 /* initialize device_num source windows (thumbnails) and boards 01430 (for a maximum of 9 additional windows and boards) */ 01431 x = x0 - src_wins_tot_w/2 + BORDER; 01432 for (i = 0; i < env->out.device_num; i++){ 01433 struct thumb_bd *p = &gui->thumb_bd_array[i]; 01434 if (set_win(gui->screen, &gui->win[i+WIN_SRC1], dpy_fmt, 01435 SRC_WIN_W, SRC_WIN_H, x+i*(BORDER+SRC_WIN_W), BORDER)) 01436 goto no_sdl; 01437 /* set geometry for the rect for the message board of the device */ 01438 p->rect.w = SRC_WIN_W; 01439 p->rect.h = SRC_MSG_BD_H; 01440 p->rect.x = x+i*(BORDER+SRC_WIN_W); 01441 p->rect.y = 2*BORDER+SRC_WIN_H; 01442 /* the white color is used as background */ 01443 SDL_FillRect(gui->screen, &p->rect, 01444 SDL_MapRGB(gui->screen->format, 255, 255, 255)); 01445 /* if necessary, initialize boards for the sources */ 01446 if (!p->board) 01447 p->board = 01448 board_setup(gui->screen, &p->rect, 01449 gui->font, gui->font_rects); 01450 /* update board rect */ 01451 SDL_UpdateRect(gui->screen, p->rect.x, p->rect.y, p->rect.w, p->rect.h); 01452 } 01453 01454 /* display the skin, but do not free it as we need it later to 01455 restore text areas and maybe sliders too */ 01456 if (gui->keypad) { 01457 struct SDL_Rect *dest = &gui->win[WIN_KEYPAD].rect; 01458 struct SDL_Rect *src = (gui->kp_rect.w > 0 && gui->kp_rect.h > 0) ? & gui->kp_rect : NULL; 01459 /* set the coordinates of the keypad relative to the main screen */ 01460 dest->x = x0-kp_w/2; 01461 dest->y = y0; 01462 dest->w = kp_w; 01463 dest->h = kp_h; 01464 SDL_BlitSurface(gui->keypad, src, gui->screen, dest); 01465 init_board(gui, &gui->bd_msg, gui->kp_msg, dest->x, dest->y); 01466 init_board(gui, &gui->bd_dialed, gui->kp_dialed, dest->x, dest->y); 01467 SDL_UpdateRects(gui->screen, 1, dest); 01468 } 01469 return; 01470 01471 no_sdl: 01472 /* free resources in case of errors */ 01473 env->gui = cleanup_sdl(gui, env->out.device_num); 01474 }
static void set_drag | ( | struct drag_info * | drag, | |
int | x, | |||
int | y, | |||
enum drag_window | win | |||
) | [static] |
Definition at line 482 of file console_gui.c.
References gui_info::drag, drag_info::drag_window, drag_info::x_start, and drag_info::y_start.
static int set_win | ( | SDL_Surface * | screen, | |
struct display_window * | win, | |||
int | fmt, | |||
int | w, | |||
int | h, | |||
int | x, | |||
int | y | |||
) | [static] |
Definition at line 1112 of file console_gui.c.
References display_window::bmp, display_window::rect, and gui_info::win.
Referenced by sdl_setup().
01114 { 01115 win->bmp = SDL_CreateYUVOverlay(w, h, fmt, screen); 01116 if (win->bmp == NULL) 01117 return -1; /* error */ 01118 win->rect.x = x; 01119 win->rect.y = y; 01120 win->rect.w = w; 01121 win->rect.h = h; 01122 return 0; 01123 }
static void show_frame | ( | struct video_desc * | env, | |
int | out | |||
) | [static] |
Definition at line 259 of file console_gui.c.
References display_window::bmp, fbuf_t::h, fbuf_t::pix_fmt, display_window::rect, fbuf_t::w, gui_info::win, WIN_LOCAL, WIN_REMOTE, and WIN_SRC1.
Referenced by hook_event_cb().
00260 { 00261 AVPicture *p_in, p_out; 00262 struct fbuf_t *b_in, *b_out; 00263 SDL_Overlay *bmp; 00264 struct gui_info *gui = env->gui; 00265 00266 if (!gui) 00267 return; 00268 00269 if (out == WIN_LOCAL) { /* webcam/x11 to sdl */ 00270 b_in = &env->enc_in; 00271 b_out = &env->loc_dpy; 00272 p_in = NULL; 00273 } else if (out == WIN_REMOTE) { 00274 /* copy input format from the decoding context */ 00275 AVCodecContext *c; 00276 if (env->in == NULL) /* XXX should not happen - decoder not ready */ 00277 return; 00278 c = env->in->dec_ctx; 00279 b_in = &env->in->dec_out; 00280 b_in->pix_fmt = c->pix_fmt; 00281 b_in->w = c->width; 00282 b_in->h = c->height; 00283 00284 b_out = &env->rem_dpy; 00285 p_in = (AVPicture *)env->in->d_frame; 00286 } else { 00287 int i = out-WIN_SRC1; 00288 b_in = env->out.devices[i].dev_buf; 00289 if (b_in == NULL) 00290 return; 00291 p_in = NULL; 00292 b_out = &env->src_dpy[i]; 00293 } 00294 bmp = gui->win[out].bmp; 00295 SDL_LockYUVOverlay(bmp); 00296 /* output picture info - this is sdl, YUV420P */ 00297 memset(&p_out, '\0', sizeof(p_out)); 00298 p_out.data[0] = bmp->pixels[0]; 00299 p_out.data[1] = bmp->pixels[1]; 00300 p_out.data[2] = bmp->pixels[2]; 00301 p_out.linesize[0] = bmp->pitches[0]; 00302 p_out.linesize[1] = bmp->pitches[1]; 00303 p_out.linesize[2] = bmp->pitches[2]; 00304 00305 my_scale(b_in, p_in, b_out, &p_out); 00306 00307 /* lock to protect access to Xlib by different threads. */ 00308 SDL_DisplayYUVOverlay(bmp, &gui->win[out].rect); 00309 SDL_UnlockYUVOverlay(bmp); 00310 }
static int switch_video_out | ( | struct video_desc * | env, | |
int | index, | |||
Uint8 | button | |||
) | [static] |
Changes the video output (local video) source, controlling if it is already using that video device, and switching the correct fields of env->out. grabbers are always open and saved in the device table. The secondary or the primary device can be changed, according to the "button" parameter: the primary device is changed if button = SDL_BUTTON_LEFT; the secondary device is changed if button = not SDL_BUTTON_LEFT;.
the correct message boards of the sources are also updated with the new status
env | = pointer to the video environment descriptor | |
index | = index of the device the caller wants to use are primary or secondary device | |
button | = button clicked on the mouse |
Definition at line 516 of file console_gui.c.
References ast_log(), IS_PRIMARY, IS_SECONDARY, LOG_WARNING, and update_device_info().
00517 { 00518 int *p; /* pointer to the index of the device to select */ 00519 00520 if (index >= env->out.device_num) { 00521 ast_log(LOG_WARNING, "no devices\n"); 00522 return 1; 00523 } 00524 /* select primary or secondary */ 00525 p = (button == SDL_BUTTON_LEFT) ? &env->out.device_primary : 00526 &env->out.device_secondary; 00527 /* controls if the device is already selected */ 00528 if (index == *p) { 00529 ast_log(LOG_WARNING, "device %s already selected\n", env->out.devices[index].name); 00530 return 0; 00531 } 00532 ast_log(LOG_WARNING, "switching to %s...\n", env->out.devices[index].name); 00533 /* already open */ 00534 if (env->out.devices[index].grabber) { 00535 /* we also have to update the messages in the source 00536 message boards below the source windows */ 00537 /* first we update the board of the previous source */ 00538 if (p == &env->out.device_primary) 00539 env->out.devices[*p].status_index &= ~IS_PRIMARY; 00540 else 00541 env->out.devices[*p].status_index &= ~IS_SECONDARY; 00542 update_device_info(env, *p); 00543 /* update the index used as primary or secondary */ 00544 *p = index; 00545 ast_log(LOG_WARNING, "done\n"); 00546 /* then we update the board of the new primary or secondary source */ 00547 if (p == &env->out.device_primary) 00548 env->out.devices[*p].status_index |= IS_PRIMARY; 00549 else 00550 env->out.devices[*p].status_index |= IS_SECONDARY; 00551 update_device_info(env, *p); 00552 return 0; 00553 } 00554 /* device is off, just do nothing */ 00555 ast_log(LOG_WARNING, "device is down\n"); 00556 return 1; 00557 }
static int turn_on_off | ( | int | index, | |
struct video_desc * | env | |||
) | [static] |
tries to switch the state of a device from on to off or off to on we also have to update the status of the device and the correct message board
index | = the device that must be turned on or off | |
env | = pointer to the video environment descriptor |
Definition at line 570 of file console_gui.c.
References ast_log(), console_grabbers, IS_ON, LOG_WARNING, grab_desc::open, and update_device_info().
00571 { 00572 struct video_device *p = &env->out.devices[index]; 00573 00574 if (index >= env->out.device_num) { 00575 ast_log(LOG_WARNING, "no devices\n"); 00576 return 0; 00577 } 00578 00579 if (!p->grabber) { /* device off */ 00580 void *g_data; /* result of grabber_open() */ 00581 struct grab_desc *g; 00582 int i; 00583 00584 /* see if the device can be used by one of the existing drivers */ 00585 for (i = 0; (g = console_grabbers[i]); i++) { 00586 /* try open the device */ 00587 g_data = g->open(p->name, &env->out.loc_src_geometry, env->out.fps); 00588 if (!g_data) /* no luck, try the next driver */ 00589 continue; 00590 p->grabber = g; 00591 p->grabber_data = g_data; 00592 /* update the status of the source */ 00593 p->status_index |= IS_ON; 00594 /* print the new message in the message board */ 00595 update_device_info(env, index); 00596 return 1; /* open succeded */ 00597 } 00598 return 0; /* failure */ 00599 } else { 00600 /* the grabber must be closed */ 00601 p->grabber_data = p->grabber->close(p->grabber_data); 00602 p->grabber = NULL; 00603 /* dev_buf is already freed by grabber->close() */ 00604 p->dev_buf = NULL; 00605 /* update the status of the source */ 00606 p->status_index &= ~IS_ON; 00607 /* print the new message in the message board */ 00608 update_device_info(env, index); 00609 return 2; /* closed */ 00610 } 00611 }
static int update_device_info | ( | struct video_desc * | env, | |
int | i | |||
) | [static] |
Definition at line 489 of file console_gui.c.
References print_message(), reset_board(), and src_msgs.
Referenced by switch_video_out(), and turn_on_off().
00490 { 00491 reset_board(env->gui->thumb_bd_array[i].board); 00492 print_message(env->gui->thumb_bd_array[i].board, 00493 src_msgs[env->out.devices[i].status_index]); 00494 return 0; 00495 }
static int video_geom | ( | struct fbuf_t * | b, | |
const char * | s | |||
) | [static] |
struct _s_k gui_key_map[] [static] |
char* src_msgs[] |
const char* const us_kbd_map[] [static] |
Definition at line 839 of file console_gui.c.