#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 89 of file console_gui.c.
00089 { 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 };
enum kp_type |
enum skin_area |
Definition at line 314 of file console_gui.c.
00314 { 00315 /* answer/close functions */ 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 /* sensitive areas for the various text windows */ 00327 KEY_MESSAGEBOARD = 140, 00328 KEY_DIALEDBOARD = 141, 00329 KEY_EDITBOARD = 142, 00330 00331 KEY_GUI_CLOSE = 199, /* close gui */ 00332 /* regions of the skin - displayed area, fonts, etc. 00333 * XXX NOTE these are not sensitive areas. 00334 */ 00335 KEY_KEYPAD = 200, /* the keypad - default to the whole image */ 00336 KEY_FONT = 201, /* the font. Maybe not really useful */ 00337 KEY_MESSAGE = 202, /* area for incoming messages */ 00338 KEY_DIALED = 203, /* area for dialed numbers */ 00339 KEY_EDIT = 204, /* area for editing user input */ 00340 00341 #ifdef notyet /* XXX for future implementation */ 00342 KEY_AUDIO_SRCS = 210, 00343 /*indexes between 210 and 219 (or more) have been reserved for the "keys" 00344 associated with the audio device markers, clicking on these markers 00345 will change the source device for audio output */ 00346 00347 #endif 00348 /* Keys related to video sources */ 00349 KEY_FREEZE = 220, /* freeze the incoming video */ 00350 KEY_CAPTURE = 221, /* capture the whole SDL window as a picture */ 00351 KEY_PIP = 230, 00352 /*indexes between 231 and 239 have been reserved for the "keys" 00353 associated with the device thumbnails, clicking on these pictures 00354 will change the source device for primary or secondary (PiP) video output*/ 00355 KEY_SRCS_WIN = 231, /* till 239 */ 00356 /* areas outside the keypad - simulated */ 00357 KEY_OUT_OF_KEYPAD = 241, 00358 KEY_REM_DPY = 242, 00359 KEY_LOC_DPY = 243, 00360 KEY_RESET = 253, /* the 'reset' keyword */ 00361 KEY_NONE = 254, /* invalid area */ 00362 KEY_DIGIT_BACKGROUND = 255, /* other areas within the keypad */ 00363 };
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 181 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.
00182 { 00183 int i; 00184 00185 if (gui == NULL) 00186 return NULL; 00187 00188 /* unload font file */ 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 /* uninitialize the SDL environment */ 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 /* deallocates the space allocated for the keypad message boards */ 00210 if (gui->bd_dialed) 00211 delete_board(gui->bd_dialed); 00212 if (gui->bd_msg) 00213 delete_board(gui->bd_msg); 00214 00215 /* deallocates the space allocated for the thumbnail message boards */ 00216 for (i = 0; i < device_num; i++) { 00217 if (gui->thumb_bd_array[i].board) /* may be useless */ 00218 delete_board(gui->thumb_bd_array[i].board); 00219 } 00220 00221 ast_free(gui); 00222 SDL_Quit(); 00223 return NULL; 00224 }
int compute_drag | ( | int * | start, | |
int | end, | |||
int | magnifier | |||
) |
Definition at line 901 of file console_gui.c.
References POLARITY.
Referenced by eventhandler().
00902 { 00903 int delta = end - *start; 00904 #define POLARITY -1 00905 /* add a small quadratic term */ 00906 delta += delta * delta * (delta > 0 ? 1 : -1 )/100; 00907 delta *= POLARITY * magnifier; 00908 #undef POLARITY 00909 *start = end; 00910 return delta; 00911 }
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 949 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.
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 /* do not react, we don't want to die because the window is minimized */ 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: /* ignore, for the time being */ 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 /* move the capture source */ 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 /* move the PiP image inside the frames of the enc_in buffers */ 01001 int dx = ev[i].motion.x - drag->x_start; 01002 int dy = ev[i].motion.y - drag->y_start; 01003 /* dx and dy value are directly applied to env->out.pip_x and 01004 env->out.pip_y, so they must work as if the format was cif */ 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 /* sets starts to a new value */ 01008 drag->x_start = ev[i].motion.x; 01009 drag->y_start = ev[i].motion.y; 01010 /* ast_log(LOG_WARNING, "moving: %d, %d\n", dx, dy); */ 01011 pip_move(env, dx, dy); 01012 } else if (drag->drag_window == DRAG_MESSAGE) { 01013 /* scroll up/down the window */ 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 //SDL_Lock_EventThread(); 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 //SDL_Unlock_EventThread(); 01036 } 01037 }
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 1058 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().
01059 { 01060 struct gui_info *gui = ast_calloc(1, sizeof(*gui)); 01061 01062 if (gui == NULL) 01063 return NULL; 01064 /* initialize keypad status */ 01065 gui->kb_output = KO_MESSAGE; /* XXX temp */ 01066 gui->drag.drag_window = DRAG_NONE; 01067 gui->outfd = -1; 01068 01069 keypad_setup(gui, keypad_file); 01070 if (gui->keypad == NULL) /* no keypad, we are done */ 01071 return gui; 01072 /* XXX load image */ 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 /* XXX hardwired constants - 3 rows of 32 chars */ 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); /* discard output, temporary */ 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 }
static int gui_map_token | ( | const char * | s | ) | [static] |
Definition at line 1532 of file console_gui.c.
References gui_key_map, _s_k::k, KEY_NONE, and _s_k::s.
Referenced by keypad_cfg_read().
01533 { 01534 /* map the string into token to be returned */ 01535 int i = atoi(s); 01536 struct _s_k *p; 01537 if (i > 0 || s[1] == '\0') /* numbers or single characters */ 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; /* not found */ 01544 }
static void handle_keyboard_input | ( | struct video_desc * | env, | |
SDL_keysym * | ks | |||
) | [static] |
Definition at line 871 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().
00872 { 00873 char buf[2] = { map_key(ks), '\0' }; 00874 struct gui_info *gui = env->gui; 00875 if (buf[0] == 0) /* modifier ? */ 00876 return; 00877 switch (gui->kb_output) { 00878 default: 00879 break; 00880 case KO_INPUT: /* to be completed */ 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: /* to be completed */ 00892 break; 00893 } 00894 00895 return; 00896 }
static void handle_mousedown | ( | struct video_desc * | env, | |
SDL_MouseButtonEvent | button | |||
) | [static] |
Definition at line 615 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().
00616 { 00617 uint8_t index = KEY_OUT_OF_KEYPAD; /* the key or region of the display we clicked on */ 00618 struct gui_info *gui = env->gui; 00619 00620 int i; /* integer variable used as iterator */ 00621 00622 int x; /* integer variable usable as a container */ 00623 00624 /* total width of source device thumbnails */ 00625 int src_wins_tot_w = env->out.device_num*(SRC_WIN_W+BORDER)+BORDER; 00626 00627 /* x coordinate of the center of the keypad */ 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 /* for each mousedown we end previous drag */ 00635 gui->drag.drag_window = DRAG_NONE; 00636 00637 /* define keypad boundary */ 00638 /* XXX this should be extended for clicks on different audio device markers */ 00639 if (button.y >= (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0)) { 00640 /* if control reaches this point this means that the clicked point is 00641 below the row of the additional sources windows*/ 00642 /* adjust the y coordinate as if additional devices windows were not present */ 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 /* we have to calculate the first coordinate 00662 inside the keypad before calling the kp_match_area*/ 00663 int x_keypad = button.x - (x0 - gui->keypad->w/2); 00664 /* find the key clicked (if one was clicked) */ 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 { /* we are in the thumbnail area */ 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 /* note that the additional device windows 00682 are numbered from left to right 00683 starting from 0, with a maximum of 8, the index associated on a click is: 00684 KEY_SRCS_WIN + number_of_the_window */ 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 /* exec the function */ 00699 if (index < 128) { /* surely clicked on the keypad, don't care which key */ 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; /* index of the window, equal to the device index in the table */ 00706 /* if one of the additional device windows is clicked with 00707 left or right mouse button, we have to switch to that device */ 00708 if (button.button == SDL_BUTTON_RIGHT || button.button == SDL_BUTTON_LEFT) { 00709 switch_video_out(env, index, button.button); 00710 return; 00711 } 00712 /* turn on or off the devices selectively with other mouse buttons */ 00713 else { 00714 int ret = turn_on_off(index, env); 00715 /* print a message according to what happened */ 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 /* XXX for future implementation 00730 else if (click on audio source marker) 00731 change audio source device 00732 */ 00733 00734 switch (index) { 00735 /* answer/close function */ 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 /* other functions */ 00744 case KEY_MUTE: /* send or not send the audio */ 00745 case KEY_AUTOANSWER: 00746 case KEY_SENDVIDEO: /* send or not send the video */ 00747 case KEY_PIP: /* activate/deactivate picture in picture mode */ 00748 case KEY_FREEZE: /* freeze/unfreeze the incoming video */ 00749 keypad_toggle(env, index); 00750 break; 00751 00752 case KEY_LOCALVIDEO: 00753 break; 00754 case KEY_REMOTEVIDEO: 00755 break; 00756 00757 #ifdef notyet /* XXX for future implementations */ 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 /* press outside the keypad. right increases size, center decreases, left drags */ 00768 case KEY_LOC_DPY: 00769 case KEY_REM_DPY: 00770 if (button.button == SDL_BUTTON_LEFT) { 00771 /* values used to find the position of the picture in picture (if present) */ 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 /* check if picture in picture is active and the click was on it */ 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 /* set the y cordinate to his previous value */ 00781 button.y += (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0); 00782 /* starts dragging the picture inside the picture */ 00783 set_drag(&gui->drag, button.x, button.y, DRAG_PIP); 00784 } 00785 else if (index == KEY_LOC_DPY) { 00786 /* set the y cordinate to his previous value */ 00787 button.y += (env->out.device_num ? SRC_WIN_H+2*BORDER+SRC_MSG_BD_H : 0); 00788 /* click in the local display, but not on the PiP */ 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 /* writes messages in the source boards, those can be 00800 modified during the execution, because of the events 00801 this must be done here, otherwise the status of sources will not be 00802 shown after sdl_setup */ 00803 for (i = 0; i < env->out.device_num; i++) { 00804 update_device_info(env, i); 00805 } 00806 /* we also have to refresh other boards, 00807 to avoid messages to disappear after video resize */ 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 }
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 1182 of file console_gui.c.
References board_setup(), gui_info::font, gui_info::font_rects, and gui_info::screen.
Referenced by sdl_setup().
01183 { 01184 if (r[0].w == 0 || r[0].h == 0) 01185 return; /* not available */ 01186 r[1] = r[0]; /* copy geometry */ 01187 r[1].x += dx; /* add offset of main window */ 01188 r[1].y += dy; 01189 if (*dst == NULL) { /* initial call */ 01190 *dst = board_setup(gui->screen, &r[1], gui->font, gui->font_rects); 01191 } else { 01192 /* call a refresh */ 01193 } 01194 }
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 1557 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().
01558 { 01559 struct keypad_entry e; 01560 SDL_Rect *r = NULL; 01561 char s1[16], s2[16]; 01562 int i, ret = 0; /* default, error */ 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; /* nothing found */ 01575 switch (i) { 01576 default: 01577 break; 01578 case 1: /* only "reset" is allowed */ 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) /* active keypad area */ 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); /* this becomes x0 */ 01595 r->y = e.x0; /* this becomes y0 */ 01596 r->w = e.y0; /* this becomes w */ 01597 r->h = e.x1; /* this becomes h */ 01598 break; 01599 } 01600 if (strcasecmp(s2, "circle")) /* invalid */ 01601 break; 01602 /* token circle xc yc diameter */ 01603 e.h = e.x1; 01604 e.y1 = e.y0; /* map radius in x1 y1 */ 01605 e.x1 = e.x0 + e.h; /* map radius in x1 y1 */ 01606 e.x0 = e.x0 - e.h; /* map radius in x1 y1 */ 01607 /* fallthrough */ 01608 01609 case 7: 01610 if (e.c == KEY_FONT) { /* font - x0 y0 w h rows cols */ 01611 ast_log(LOG_WARNING, "font not supported yet\n"); 01612 break; 01613 } 01614 /* token circle|rect x0 y0 x1 y1 h */ 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 /* for a circle we specify the diameter but store center and radii */ 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 // ast_log(LOG_WARNING, "reading [%s] returns %d %d\n", val, i, ret); 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) { /* must allocate */ 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 // ast_log(LOG_WARNING, "now %d regions\n", gui->kp_used); 01656 return 1; 01657 }
static void keypad_digit | ( | struct video_desc * | env, | |
int | digit | |||
) | [static] |
Definition at line 370 of file console_gui.c.
References AST_FRAME_DTMF, ast_queue_frame(), f, and print_message().
00371 { 00372 if (env->owner) { /* we have a call, send the digit */ 00373 struct ast_frame f = { AST_FRAME_DTMF, 0 }; 00374 00375 f.subclass = digit; 00376 ast_queue_frame(env->owner, &f); 00377 } else { /* no call, accumulate digits */ 00378 char buf[2] = { digit, '\0' }; 00379 if (env->gui->bd_msg) /* XXX not strictly necessary ... */ 00380 print_message(env->gui->bd_msg, buf); 00381 } 00382 }
static void keypad_pick_up | ( | struct video_desc * | env | ) | [static] |
Definition at line 428 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().
00429 { 00430 struct gui_info *gui = env->gui; 00431 00432 ast_log(LOG_WARNING, "keypad_pick_up called\n"); 00433 00434 if (env->owner) { /* someone is calling us, just answer */ 00435 ast_cli_command(gui->outfd, "console answer"); 00436 } else { /* we have someone to call */ 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 }
static void keypad_setup | ( | struct gui_info * | gui, | |
const char * | kp_file | |||
) | [static] |
Definition at line 1123 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().
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 /* now try to read the keymap from the file. */ 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 * If the keypad image has a comment field, try to read 01144 * the button location from there. The block must start with 01145 * a comment (or empty) line, and continue with entries like: 01146 * region = token shape x0 y0 x1 y1 h 01147 * ... 01148 * (basically, lines have the same format as config file entries). 01149 * You can add it to a jpeg file using wrjpgcom 01150 */ 01151 while (fgets(buf, sizeof(buf), fd)) { 01152 char *s; 01153 01154 if (!strstr(buf, region)) { /* no keyword yet */ 01155 if (!in_comment) /* still waiting for initial comment block */ 01156 continue; 01157 else 01158 break; 01159 } 01160 if (!in_comment) { /* first keyword, reset previous entries */ 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; /* keyword not found */ 01168 s = ast_skip_blanks(s + reg_len); /* space between token and '=' */ 01169 if (*s++ != '=') /* missing separator */ 01170 break; 01171 if (*s == '>') /* skip '>' if present */ 01172 s++; 01173 keypad_cfg_read(gui, ast_skip_blanks(s)); 01174 } 01175 fclose(fd); 01176 }
static char* keypad_toggle | ( | struct video_desc * | env, | |
int | index | |||
) | [static] |
Definition at line 385 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.
00386 { 00387 ast_log(LOG_WARNING, "keypad_toggle(%i) called\n", index); 00388 00389 switch (index) { 00390 case KEY_SENDVIDEO: /* send or do not send video */ 00391 env->out.sendvideo = !env->out.sendvideo; 00392 break; 00393 00394 case KEY_PIP: /* enable or disable Picture in Picture */ 00395 env->out.picture_in_picture = !env->out.picture_in_picture; 00396 break; 00397 00398 case KEY_MUTE: /* send or do not send audio */ 00399 ast_cli_command(env->gui->outfd, "console mute toggle"); 00400 break; 00401 00402 case KEY_FREEZE: /* freeze/unfreeze the incoming frames */ 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 }
static int kp_match_area | ( | const struct keypad_entry * | e, | |
int | x, | |||
int | y | |||
) | [static] |
Definition at line 1483 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().
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) { /* large enough */ 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 }
static SDL_Surface* load_image | ( | const char * | file | ) | [static] |
Definition at line 1039 of file console_gui.c.
Referenced by gui_init(), and keypad_setup().
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 }
static char map_key | ( | SDL_keysym * | ks | ) | [static] |
Definition at line 843 of file console_gui.c.
Referenced by handle_keyboard_input().
00844 { 00845 const char *s, **p = us_kbd_map; 00846 int c = ks->sym; 00847 00848 if (c == '\r') /* map cr into lf */ 00849 c = '\n'; 00850 if (c >= SDLK_NUMLOCK && c <= SDLK_COMPOSE) 00851 return 0; /* only a modifier */ 00852 if (ks->mod == 0) 00853 return c; 00854 while ((s = *p) && s[0] != c) 00855 p++; 00856 if (s) { /* see if we have a modifier and a chance to use it */ 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 }
static int my_x_handler | ( | Display * | d, | |
XErrorEvent * | e | |||
) | [static] |
Definition at line 1204 of file console_gui.c.
References ast_log(), and LOG_WARNING.
Referenced by sdl_setup().
01205 { 01206 ast_log(LOG_WARNING, "%s error_code %d\n", __FUNCTION__, e->error_code); 01207 return 0; 01208 }
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 921 of file console_gui.c.
Referenced by eventhandler().
00921 { 00922 int new_pip_x = env->out.pip_x+dx; 00923 int new_pip_y = env->out.pip_y+dy; 00924 /* going beyond the left borders */ 00925 if (new_pip_x < 0) 00926 new_pip_x = 0; 00927 /* going beyond the right borders */ 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 /* going beyond the top borders */ 00931 if (new_pip_y < 0) 00932 new_pip_y = 0; 00933 /* going beyond the bottom borders */ 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 }
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 1215 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.
01216 { 01217 int dpy_fmt = SDL_IYUV_OVERLAY; /* YV12 causes flicker in SDL */ 01218 int depth, maxw, maxh; 01219 const SDL_VideoInfo *info; 01220 int kp_w = 0, kp_h = 0; /* keypad width and height */ 01221 struct gui_info *gui = env->gui; 01222 01223 /* Some helper variables used for filling the SDL window */ 01224 int x0; /* the x coordinate of the center of the keypad */ 01225 int x1; /* userful for calculating of the size of the parent window */ 01226 int y0; /* y coordinate of the keypad, the remote window and the local window */ 01227 int src_wins_tot_w; /* total width of the source windows */ 01228 int i; 01229 int x; /* useful for the creation of the source windows; */ 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 * initialize the SDL environment. We have one large window 01250 * with local and remote video, and a keypad. 01251 * At the moment we arrange them statically, as follows: 01252 * - top row: thumbnails for local video sources; 01253 * - next row: message boards for local video sources 01254 * - on the left, the remote video; 01255 * - on the center, the keypad 01256 * - on the right, the local video 01257 * We need to read in the skin for the keypad before creating the main 01258 * SDL window, because the size is only known here. 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 /* again not fatal, just we won't display anything */ 01265 return; 01266 } 01267 info = SDL_GetVideoInfo(); 01268 /* We want at least 16bpp to support YUV overlays. 01269 * E.g with SDL_VIDEODRIVER = aalib the default is 8 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 /* total width of the thumbnails */ 01295 src_wins_tot_w = env->out.device_num*(SRC_WIN_W+BORDER)+BORDER; 01296 01297 /* x coordinate of the center of the keypad */ 01298 x0 = MAX(env->rem_dpy.w+kp_w/2+2*BORDER, src_wins_tot_w/2); 01299 01300 /* from center of the keypad to right border */ 01301 x1 = MAX(env->loc_dpy.w+kp_w/2+2*BORDER, src_wins_tot_w/2); 01302 01303 /* total width of the SDL window to create */ 01304 maxw = x0+x1; 01305 01306 /* total height of the mother window to create */ 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 * Annoying as it may be, if SDL_WINDOWID is set, SDL does 01319 * not grab keyboard/mouse events or expose or other stuff, 01320 * and it does not handle resize either. 01321 * So we need to implement workarounds here. 01322 */ 01323 do { 01324 /* First, handle the event mask */ 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)) /* no external window, don't bother doing this */ 01333 break; 01334 SDL_VERSION(&info.version); /* it is important to set the 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 * A list of events we want. 01346 * Leave ResizeRedirectMask to the parent. 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 | /* ResizeRedirectMask | */ 01357 SubstructureNotifyMask | SubstructureRedirectMask | 01358 FocusChangeMask | PropertyChangeMask | 01359 ColormapChangeMask | OwnerGrabButtonMask; 01360 01361 memset(&attr, '\0', sizeof(attr)); 01362 XGetWindowAttributes(SDL_Display, win, &attr); 01363 01364 /* the following events can be delivered only to one client. 01365 * So check which ones are going to someone else, and drop 01366 * them from our request. 01367 */ 01368 { 01369 /* ev are the events for a single recipient */ 01370 long ev = ButtonPressMask | ResizeRedirectMask | 01371 SubstructureRedirectMask; 01372 ev &= (attr.all_event_masks & ~attr.your_event_mask); 01373 /* now ev contains 1 for single-recipient events owned by others. 01374 * We must clear those bits in 'want' 01375 * and then add the bits in 'attr.your_event_mask' to 'want' 01376 */ 01377 want &= ~ev; 01378 want |= attr.your_event_mask; 01379 } 01380 XSelectInput(SDL_Display, win, want); 01381 01382 /* Second, handle resize. 01383 * We do part of the things that X11Resize does, 01384 * but also generate a ConfigureNotify event so 01385 * the owner of the window has a chance to do something 01386 * with it. 01387 */ 01388 XResizeWindow(SDL_Display, win, maxw, maxh); 01389 { 01390 XConfigureEvent ce = { 01391 .type = ConfigureNotify, 01392 .serial = 0, 01393 .send_event = 1, /* TRUE */ 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 /* TRUE */, StructureNotifyMask, (XEvent *)&ce); 01405 } 01406 } while (0); 01407 #endif /* HAVE_X11 */ 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 /* intialize the windows for local and remote video */ 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 /* unfreeze incoming frames if set (to avoid showing nothing) */ 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 /* initialize device_num source windows (thumbnails) and boards 01426 (for a maximum of 9 additional windows and boards) */ 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 /* set geometry for the rect for the message board of the device */ 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 /* the white color is used as background */ 01439 SDL_FillRect(gui->screen, &p->rect, 01440 SDL_MapRGB(gui->screen->format, 255, 255, 255)); 01441 /* if necessary, initialize boards for the sources */ 01442 if (!p->board) 01443 p->board = 01444 board_setup(gui->screen, &p->rect, 01445 gui->font, gui->font_rects); 01446 /* update board rect */ 01447 SDL_UpdateRect(gui->screen, p->rect.x, p->rect.y, p->rect.w, p->rect.h); 01448 } 01449 01450 /* display the skin, but do not free it as we need it later to 01451 restore text areas and maybe sliders too */ 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 /* set the coordinates of the keypad relative to the main screen */ 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 /* free resources in case of errors */ 01469 env->gui = cleanup_sdl(gui, env->out.device_num); 01470 }
static void set_drag | ( | struct drag_info * | drag, | |
int | x, | |||
int | y, | |||
enum drag_window | win | |||
) | [static] |
Definition at line 478 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 1108 of file console_gui.c.
References display_window::bmp, display_window::rect, and gui_info::win.
Referenced by sdl_setup().
01110 { 01111 win->bmp = SDL_CreateYUVOverlay(w, h, fmt, screen); 01112 if (win->bmp == NULL) 01113 return -1; /* error */ 01114 win->rect.x = x; 01115 win->rect.y = y; 01116 win->rect.w = w; 01117 win->rect.h = h; 01118 return 0; 01119 }
static void show_frame | ( | struct video_desc * | env, | |
int | out | |||
) | [static] |
Definition at line 255 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().
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) { /* webcam/x11 to sdl */ 00266 b_in = &env->enc_in; 00267 b_out = &env->loc_dpy; 00268 p_in = NULL; 00269 } else if (out == WIN_REMOTE) { 00270 /* copy input format from the decoding context */ 00271 AVCodecContext *c; 00272 if (env->in == NULL) /* XXX should not happen - decoder not ready */ 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 /* output picture info - this is sdl, YUV420P */ 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 /* lock to protect access to Xlib by different threads. */ 00304 SDL_DisplayYUVOverlay(bmp, &gui->win[out].rect); 00305 SDL_UnlockYUVOverlay(bmp); 00306 }
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 512 of file console_gui.c.
References ast_log(), IS_PRIMARY, IS_SECONDARY, LOG_WARNING, and update_device_info().
00513 { 00514 int *p; /* pointer to the index of the device to select */ 00515 00516 if (index >= env->out.device_num) { 00517 ast_log(LOG_WARNING, "no devices\n"); 00518 return 1; 00519 } 00520 /* select primary or secondary */ 00521 p = (button == SDL_BUTTON_LEFT) ? &env->out.device_primary : 00522 &env->out.device_secondary; 00523 /* controls if the device is already selected */ 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 /* already open */ 00530 if (env->out.devices[index].grabber) { 00531 /* we also have to update the messages in the source 00532 message boards below the source windows */ 00533 /* first we update the board of the previous source */ 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 /* update the index used as primary or secondary */ 00540 *p = index; 00541 ast_log(LOG_WARNING, "done\n"); 00542 /* then we update the board of the new primary or secondary source */ 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 /* device is off, just do nothing */ 00551 ast_log(LOG_WARNING, "device is down\n"); 00552 return 1; 00553 }
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 566 of file console_gui.c.
References ast_log(), console_grabbers, IS_ON, LOG_WARNING, grab_desc::open, and update_device_info().
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) { /* device off */ 00576 void *g_data; /* result of grabber_open() */ 00577 struct grab_desc *g; 00578 int i; 00579 00580 /* see if the device can be used by one of the existing drivers */ 00581 for (i = 0; (g = console_grabbers[i]); i++) { 00582 /* try open the device */ 00583 g_data = g->open(p->name, &env->out.loc_src_geometry, env->out.fps); 00584 if (!g_data) /* no luck, try the next driver */ 00585 continue; 00586 p->grabber = g; 00587 p->grabber_data = g_data; 00588 /* update the status of the source */ 00589 p->status_index |= IS_ON; 00590 /* print the new message in the message board */ 00591 update_device_info(env, index); 00592 return 1; /* open succeded */ 00593 } 00594 return 0; /* failure */ 00595 } else { 00596 /* the grabber must be closed */ 00597 p->grabber_data = p->grabber->close(p->grabber_data); 00598 p->grabber = NULL; 00599 /* dev_buf is already freed by grabber->close() */ 00600 p->dev_buf = NULL; 00601 /* update the status of the source */ 00602 p->status_index &= ~IS_ON; 00603 /* print the new message in the message board */ 00604 update_device_info(env, index); 00605 return 2; /* closed */ 00606 } 00607 }
static int update_device_info | ( | struct video_desc * | env, | |
int | i | |||
) | [static] |
Definition at line 485 of file console_gui.c.
References print_message(), reset_board(), and src_msgs.
Referenced by switch_video_out(), and turn_on_off().
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 }
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 835 of file console_gui.c.