dect
/
asterisk
Archived
13
0
Fork 0

more preparation for untangling of the various console_video stuff

git-svn-id: http://svn.digium.com/svn/asterisk/trunk@94805 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
rizzo 2007-12-26 20:01:16 +00:00
parent 9b60268827
commit 4d04a3258e
4 changed files with 199 additions and 130 deletions

View File

@ -4,30 +4,73 @@
* $Revision$
*/
#include "asterisk.h"
#include "console_video.h"
#include "asterisk/lock.h"
#include "asterisk/frame.h"
#include "asterisk/utils.h" /* ast_calloc and ast_realloc */
#include <math.h> /* sqrt */
enum kp_type { KP_NONE, KP_RECT, KP_CIRCLE };
struct keypad_entry {
int c; /* corresponding character */
int x0, y0, x1, y1, h; /* arguments */
enum kp_type type;
};
#define GUI_BUFFER_LEN 256 /* buffer lenght used for input buffers */
struct keypad_entry; /* defined in console_gui.c */
/*! \brief info related to the gui: button status, mouse coords, etc. */
struct gui_info {
char inbuf[GUI_BUFFER_LEN]; /* buffer for to-dial buffer */
int inbuf_pos; /* next free position in inbuf */
char msgbuf[GUI_BUFFER_LEN]; /* buffer for text-message buffer */
int msgbuf_pos; /* next free position in msgbuf */
int text_mode; /* switch to-dial and text-message mode */
int drag_mode; /* switch phone and drag-source mode */
int x_drag; /* x coordinate where the drag starts */
int y_drag; /* y coordinate where the drag starts */
#ifdef HAVE_SDL_TTF
TTF_Font *font; /* font to be used */
#endif
int outfd; /* fd for output */
SDL_Surface *keypad; /* the pixmap for the keypad */
int kp_size, kp_used;
struct keypad_entry *kp;
};
static void cleanup_sdl(struct video_desc *env)
{
int i;
struct gui_info *gui = env->gui;
if (gui) {
#ifdef HAVE_SDL_TTF
/* unload font file */
if (env->gui.font) {
TTF_CloseFont(env->gui.font);
env->gui.font = NULL;
if (gui->font) {
TTF_CloseFont(gui->font);
gui->font = NULL;
}
/* uninitialize SDL_ttf library */
if ( TTF_WasInit() )
TTF_Quit();
#endif
if (gui->keypad)
SDL_FreeSurface(gui->keypad);
gui->keypad = NULL;
/* XXX free the keys entries */
ast_free(gui);
env->gui = NULL;
}
/* uninitialize the SDL environment */
for (i = 0; i < WIN_MAX; i++) {
if (env->win[i].bmp)
SDL_FreeYUVOverlay(env->win[i].bmp);
}
if (env->gui.keypad)
SDL_FreeSurface(env->gui.keypad);
env->gui.keypad = NULL;
SDL_Quit();
env->screen = NULL; /* XXX check reference */
bzero(env->win, sizeof(env->win));
@ -177,7 +220,7 @@ static void keypad_digit(struct video_desc *env, int digit)
f.subclass = digit;
ast_queue_frame(env->owner, &f);
} else { /* no call, accumulate digits */
append_char(env->gui.inbuf, &env->gui.inbuf_pos, digit);
append_char(env->gui->inbuf, &env->gui->inbuf_pos, digit);
}
}
@ -186,7 +229,7 @@ static void keypad_digit(struct video_desc *env, int digit)
static void keypad_send_command(struct video_desc *env, char *command)
{
ast_log(LOG_WARNING, "keypad_send_command(%s) called\n", command);
ast_cli_command(env->gui.outfd, command);
ast_cli_command(env->gui->outfd, command);
return;
}
@ -228,15 +271,17 @@ char *console_do_answer(int fd);
*/
static void keypad_pick_up(struct video_desc *env)
{
struct gui_info *gui = env->gui;
ast_log(LOG_WARNING, "keypad_pick_up called\n");
if (env->owner) { /* someone is calling us, just answer */
console_do_answer(-1);
} else if (env->gui.inbuf_pos) { /* we have someone to call */
ast_cli_command(env->gui.outfd, env->gui.inbuf);
} else if (gui->inbuf_pos) { /* we have someone to call */
ast_cli_command(gui->outfd, gui->inbuf);
}
append_char(env->gui.inbuf, &env->gui.inbuf_pos, '\0'); /* clear buffer */
append_char(gui->inbuf, &gui->inbuf_pos, '\0'); /* clear buffer */
}
#if 0 /* still unused */
@ -267,11 +312,12 @@ static int gui_output(struct video_desc *env, const char *text)
SDL_Surface *output = NULL;
SDL_Color color = {0, 0, 0}; /* text color */
SDL_Rect dest = {env->win[WIN_KEYPAD].rect.x + x, y};
struct gui_info *gui = env->gui;
/* clean surface each rewrite */
SDL_BlitSurface(env->gui.keypad, NULL, env->screen, &env->win[WIN_KEYPAD].rect);
SDL_BlitSurface(gui->keypad, NULL, env->screen, &env->win[WIN_KEYPAD].rect);
output = TTF_RenderText_Solid(env->gui.font, text, color);
output = TTF_RenderText_Solid(gui->font, text, color);
if (output == NULL) {
ast_log(LOG_WARNING, "Cannot render text on gui - %s\n", TTF_GetError());
return 1;
@ -279,7 +325,7 @@ static int gui_output(struct video_desc *env, const char *text)
SDL_BlitSurface(output, NULL, env->screen, &dest);
SDL_UpdateRects(env->gui.keypad, 1, &env->win[WIN_KEYPAD].rect);
SDL_UpdateRects(gui->keypad, 1, &env->win[WIN_KEYPAD].rect);
SDL_FreeSurface(output);
return 0; /* success */
#endif
@ -300,8 +346,12 @@ static void handle_button_event(struct video_desc *env, SDL_MouseButtonEvent but
{
uint8_t index = KEY_OUT_OF_KEYPAD; /* the key or region of the display we clicked on */
#if 0
ast_log(LOG_WARNING, "event %d %d have %d/%d regions at %p\n",
button.x, button.y, env->gui->kp_used, env->gui->kp_size, env->gui->kp);
#endif
/* for each click we come back in normal mode */
env->gui.text_mode = 0;
env->gui->text_mode = 0;
/* define keypad boundary */
if (button.x < env->in.rem_dpy.w)
@ -310,11 +360,11 @@ static void handle_button_event(struct video_desc *env, SDL_MouseButtonEvent but
index = KEY_LOC_DPY; /* click on local video */
else if (button.y > env->out.keypad_dpy.h)
index = KEY_OUT_OF_KEYPAD; /* click outside the keypad */
else if (env->gui.kp) {
else if (env->gui->kp) {
int i;
for (i = 0; i < env->gui.kp_used; i++) {
if (kp_match_area(&env->gui.kp[i], button.x - env->in.rem_dpy.w, button.y)) {
index = env->gui.kp[i].c;
for (i = 0; i < env->gui->kp_used; i++) {
if (kp_match_area(&env->gui->kp[i], button.x - env->in.rem_dpy.w, button.y)) {
index = env->gui->kp[i].c;
break;
}
}
@ -347,7 +397,7 @@ static void handle_button_event(struct video_desc *env, SDL_MouseButtonEvent but
break;
case KEY_WRITEMESSAGE:
/* goes in text-mode */
env->gui.text_mode = 1;
env->gui->text_mode = 1;
break;
@ -358,9 +408,9 @@ static void handle_button_event(struct video_desc *env, SDL_MouseButtonEvent but
if (index == KEY_LOC_DPY) {
/* store points where the drag start
* and switch in drag mode */
env->gui.x_drag = button.x;
env->gui.y_drag = button.y;
env->gui.drag_mode = 1;
env->gui->x_drag = button.x;
env->gui->y_drag = button.y;
env->gui->drag_mode = 1;
}
break;
} else {
@ -394,20 +444,20 @@ static void handle_button_event(struct video_desc *env, SDL_MouseButtonEvent but
*/
static void handle_keyboard_input(struct video_desc *env, SDLKey key)
{
if (env->gui.text_mode) {
if (env->gui->text_mode) {
/* append in the text-message buffer */
if (key == SDLK_RETURN) {
/* send the text message and return in normal mode */
env->gui.text_mode = 0;
env->gui->text_mode = 0;
keypad_send_command(env, "send text");
} else {
/* accumulate the key in the message buffer */
append_char(env->gui.msgbuf, &env->gui.msgbuf_pos, key);
append_char(env->gui->msgbuf, &env->gui->msgbuf_pos, key);
}
}
else {
/* append in the dial buffer */
append_char(env->gui.inbuf, &env->gui.inbuf_pos, key);
append_char(env->gui->inbuf, &env->gui->inbuf_pos, key);
}
return;
@ -445,11 +495,11 @@ static void move_capture_source(struct video_desc *env, int x_final_drag, int y_
/* move the origin */
#define POLARITY -1 /* +1 or -1 depending on the desired direction */
new_x = x + POLARITY*move_accel(x_final_drag - env->gui.x_drag) * 3;
new_y = y + POLARITY*move_accel(y_final_drag - env->gui.y_drag) * 3;
new_x = x + POLARITY*move_accel(x_final_drag - env->gui->x_drag) * 3;
new_y = y + POLARITY*move_accel(y_final_drag - env->gui->y_drag) * 3;
#undef POLARITY
env->gui.x_drag = x_final_drag; /* update origin */
env->gui.y_drag = y_final_drag;
env->gui->x_drag = x_final_drag; /* update origin */
env->gui->y_drag = y_final_drag;
/* check boundary and let the source to grab from the new points */
env->out.loc_src.x = boundary_checks(new_x, env->out.screen_width - env->out.loc_src.w);
@ -483,16 +533,16 @@ static void eventhandler(struct video_desc *env)
handle_keyboard_input(env, ev[i].key.keysym.sym);
break;
case SDL_MOUSEMOTION:
if (env->gui.drag_mode != 0)
if (env->gui->drag_mode != 0)
move_capture_source(env, ev[i].motion.x, ev[i].motion.y);
break;
case SDL_MOUSEBUTTONDOWN:
handle_button_event(env, ev[i].button);
break;
case SDL_MOUSEBUTTONUP:
if (env->gui.drag_mode != 0) {
if (env->gui->drag_mode != 0) {
move_capture_source(env, ev[i].button.x, ev[i].button.y);
env->gui.drag_mode = 0;
env->gui->drag_mode = 0;
}
break;
}
@ -529,43 +579,50 @@ static SDL_Surface *get_keypad(const char *file)
/* TODO: consistency checks, check for bpp, widht and height */
/* Init the mask image used to grab the action. */
static int gui_init(struct video_desc *env)
static struct gui_info *gui_init(struct video_desc *env)
{
struct gui_info *gui = ast_calloc(1, sizeof(*gui));
if (gui == NULL)
return NULL;
/* initialize keypad status */
env->gui.text_mode = 0;
env->gui.drag_mode = 0;
gui->text_mode = 0;
gui->drag_mode = 0;
/* initialize grab coordinates */
env->out.loc_src.x = 0;
env->out.loc_src.y = 0;
/* initialize keyboard buffer */
append_char(env->gui.inbuf, &env->gui.inbuf_pos, '\0');
append_char(env->gui.msgbuf, &env->gui.msgbuf_pos, '\0');
append_char(gui->inbuf, &gui->inbuf_pos, '\0');
append_char(gui->msgbuf, &gui->msgbuf_pos, '\0');
#ifdef HAVE_SDL_TTF
/* Initialize SDL_ttf library and load font */
if (TTF_Init() == -1) {
ast_log(LOG_WARNING, "Unable to init SDL_ttf, no output available\n");
return -1;
goto error;
}
#define GUI_FONTSIZE 28
env->gui.font = TTF_OpenFont( env->keypad_font, GUI_FONTSIZE);
if (!env->gui.font) {
gui->font = TTF_OpenFont( env->keypad_font, GUI_FONTSIZE);
if (!gui->font) {
ast_log(LOG_WARNING, "Unable to load font %s, no output available\n", env->keypad_font);
return -1;
goto error;
}
ast_log(LOG_WARNING, "Loaded font %s\n", env->keypad_font);
#endif
env->gui.outfd = open ("/dev/null", O_WRONLY); /* discard output, temporary */
if ( env->gui.outfd < 0 ) {
gui->outfd = open ("/dev/null", O_WRONLY); /* discard output, temporary */
if (gui->outfd < 0) {
ast_log(LOG_WARNING, "Unable output fd\n");
return -1;
goto error;
}
return gui;
return 0;
error:
ast_free(gui);
return NULL;
}
/* setup an sdl overlay and associated info, return 0 on success, != 0 on error */
@ -590,14 +647,14 @@ static void keypad_setup(struct video_desc *env)
void *p = NULL;
off_t l = 0;
if (env->gui.keypad)
if (env->gui->keypad)
return;
env->gui.keypad = get_keypad(env->keypad_file);
if (!env->gui.keypad)
env->gui->keypad = get_keypad(env->keypad_file);
if (!env->gui->keypad)
return;
env->out.keypad_dpy.w = env->gui.keypad->w;
env->out.keypad_dpy.h = env->gui.keypad->h;
env->out.keypad_dpy.w = env->gui->keypad->w;
env->out.keypad_dpy.h = env->gui->keypad->h;
/*
* If the keypad image has a comment field, try to read
* the button location from there. The block must be
@ -631,7 +688,7 @@ static void keypad_setup(struct video_desc *env)
for (s = p; s < e - 20 ; s++) {
if (!memcmp(s, region, reg_len)) { /* keyword found */
/* reset previous entries */
keypad_cfg_read(&env->gui, "reset");
keypad_cfg_read(env->gui, "reset");
break;
}
}
@ -652,7 +709,7 @@ static void keypad_setup(struct video_desc *env)
break;
if (*s1 == '>') /* skip => */
s1++;
keypad_cfg_read(&env->gui, ast_skip_blanks(s1));
keypad_cfg_read(env->gui, ast_skip_blanks(s1));
/* now wait for a newline */
s1 = s;
while (s1 < e - 20 && !index("\r\n", *s1) && *s1 < 128)
@ -686,9 +743,17 @@ static void sdl_setup(struct video_desc *env)
* - on the left, the remote video;
* - on the center, the keypad
* - on the right, the local video
* We need to read in the skin for the keypad before creating the main
* SDL window, because the size is only known here.
*/
keypad_setup(env);
env->gui = gui_init(env);
ast_log(LOG_WARNING, "gui_init returned %p\n", env->gui);
if (env->gui) {
keypad_setup(env);
ast_log(LOG_WARNING, "keypad_setup returned %p %d\n",
env->gui->keypad, env->gui->kp_used);
}
#define BORDER 5 /* border around our windows */
maxw = env->in.rem_dpy.w + env->out.loc_dpy.w + env->out.keypad_dpy.w;
maxh = MAX( MAX(env->in.rem_dpy.h, env->out.loc_dpy.h), env->out.keypad_dpy.h);
@ -712,13 +777,13 @@ static void sdl_setup(struct video_desc *env)
/* display the skin, but do not free it as we need it later to
* restore text areas and maybe sliders too.
*/
if (env->gui.keypad) {
if (env->gui && env->gui->keypad) {
struct SDL_Rect *dest = &env->win[WIN_KEYPAD].rect;
dest->x = 2*BORDER + env->in.rem_dpy.w;
dest->y = BORDER;
dest->w = env->gui.keypad->w;
dest->h = env->gui.keypad->h;
SDL_BlitSurface(env->gui.keypad, NULL, env->screen, dest);
dest->w = env->gui->keypad->w;
dest->h = env->gui->keypad->h;
SDL_BlitSurface(env->gui->keypad, NULL, env->screen, dest);
SDL_UpdateRects(env->screen, 1, dest);
}
env->in.dec_in_cur = &env->in.dec_in[0];
@ -765,15 +830,6 @@ static int kp_match_area(const struct keypad_entry *e, int x, int y)
return ret;
}
/*
* 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 is the token to be returned, either a character or a symbol
* as KEY_* above
*/
struct _s_k { const char *s; int k; };
static struct _s_k gui_key_map[] = {
{"PICK_UP", KEY_PICK_UP },
@ -789,12 +845,24 @@ static struct _s_k gui_key_map[] = {
{"GUI_CLOSE", KEY_GUI_CLOSE },
{NULL, 0 } };
/*! \brief 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 is the token to be returned, either a character or a symbol
* as KEY_* above
* Return 1 on success, 0 on error.
*/
static int keypad_cfg_read(struct gui_info *gui, const char *val)
{
struct keypad_entry e;
char s1[16], s2[16];
int i, ret = 0;
if (gui == NULL || val == NULL)
return 0;
bzero(&e, sizeof(e));
i = sscanf(val, "%14s %14s %d %d %d %d %d",
s1, s2, &e.x0, &e.y0, &e.x1, &e.y1, &e.h);
@ -876,5 +944,6 @@ static int keypad_cfg_read(struct gui_info *gui, const char *val)
if (gui->kp_size == gui->kp_used)
return 0;
gui->kp[gui->kp_used++] = e;
ast_log(LOG_WARNING, "now %d regions\n", gui->kp_used);
return 1;
}

View File

@ -22,7 +22,6 @@
#include "asterisk.h"
#include <sys/ioctl.h>
#include <math.h> /* sqrt */
#include "asterisk/cli.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
@ -250,43 +249,6 @@ struct video_in_desc {
struct fbuf_t rem_dpy; /* display remote image, no buffer (it is in win[WIN_REMOTE].bmp) */
};
/* our representation of a displayed window. SDL can only do one main
* window so we map everything within that one
*/
enum { WIN_LOCAL, WIN_REMOTE, WIN_KEYPAD, WIN_MAX };
struct display_window {
SDL_Overlay *bmp;
SDL_Rect rect; /* loc. of images */
};
#define GUI_BUFFER_LEN 256 /* buffer lenght used for input buffers */
enum kp_type { KP_NONE, KP_RECT, KP_CIRCLE };
struct keypad_entry {
int c; /* corresponding character */
int x0, y0, x1, y1, h; /* arguments */
enum kp_type type;
};
/*! \brief info related to the gui: button status, mouse coords, etc. */
struct gui_info {
char inbuf[GUI_BUFFER_LEN]; /* buffer for to-dial buffer */
int inbuf_pos; /* next free position in inbuf */
char msgbuf[GUI_BUFFER_LEN]; /* buffer for text-message buffer */
int msgbuf_pos; /* next free position in msgbuf */
int text_mode; /* switch to-dial and text-message mode */
int drag_mode; /* switch phone and drag-source mode */
int x_drag; /* x coordinate where the drag starts */
int y_drag; /* y coordinate where the drag starts */
#ifdef HAVE_SDL_TTF
TTF_Font *font; /* font to be used */
#endif
int outfd; /* fd for output */
SDL_Surface *keypad; /* the pixmap for the keypad */
int kp_size, kp_used;
struct keypad_entry *kp;
};
/*
* The overall descriptor, with room for config info, video source and
@ -302,11 +264,10 @@ struct video_desc {
struct video_in_desc in; /* remote video descriptor */
struct video_out_desc out; /* local video descriptor */
struct gui_info gui;
struct gui_info *gui;
/* support for display. */
int sdl_ok;
int gui_ok;
SDL_Surface *screen; /* the main window */
char keypad_file[256]; /* image for the keypad */
char keypad_font[256]; /* font for the keypad */
@ -1147,10 +1108,6 @@ static void *video_thread(void *arg)
sdl_setup(env);
if (env->sdl_ok)
ast_mutex_init(&env->in.dec_in_lock);
/* TODO, segfault if not X display present */
env->gui_ok = !gui_init(env);
if (!env->gui_ok)
ast_log(LOG_WARNING, "cannot init console gui\n");
}
if (!ast_strlen_zero(save_display))
setenv("DISPLAY", save_display, 1);
@ -1190,7 +1147,7 @@ static void *video_thread(void *arg)
/* manage keypad events */
/* XXX here we should always check for events,
* otherwise the drag will not work */
if (env->gui_ok)
if (env->gui)
eventhandler(env);
/* sleep for a while */
@ -1447,7 +1404,7 @@ int console_video_config(struct video_desc **penv,
CV_F("local_size", video_geom(&env->out.loc_dpy, val));
CV_F("remote_size", video_geom(&env->in.rem_dpy, val));
CV_STR("keypad", env->keypad_file);
CV_F("region", keypad_cfg_read(&env->gui, val));
CV_F("region", keypad_cfg_read(env->gui, val));
CV_STR("keypad_font", env->keypad_font);
CV_STR("sdl_videodriver", env->sdl_videodriver);
CV_UINT("fps", env->out.fps);

View File

@ -20,8 +20,55 @@
* $Revision$
*/
struct video_desc; /* opaque type for video support */
#ifndef CONSOLE_VIDEO_H
#define CONSOLE_VIDEO_H
#if !defined(HAVE_VIDEO_CONSOLE) || !defined(HAVE_FFMPEG) || !defined(HAVE_SDL)
#define CONSOLE_VIDEO_CMDS \
"console {device}"
#else
#ifdef HAVE_X11
#include <X11/Xlib.h> /* this should be conditional */
#endif
#include <ffmpeg/avcodec.h>
#ifndef OLD_FFMPEG
#include <ffmpeg/swscale.h> /* requires a recent ffmpeg */
#endif
#include <SDL/SDL.h>
#ifdef HAVE_SDL_IMAGE
#include <SDL/SDL_image.h> /* for loading images */
#endif
#ifdef HAVE_SDL_TTF
#include <SDL/SDL_ttf.h> /* render text on sdl surfaces */
#endif
/* our representation of a displayed window. SDL can only do one main
* window so we map everything within that one
*/
enum { WIN_LOCAL, WIN_REMOTE, WIN_KEYPAD, WIN_MAX };
/* our representation of a displayed window. SDL can only do one main
* window so we map everything within that one
*/
struct display_window {
SDL_Overlay *bmp;
SDL_Rect rect; /* location of the window */
};
#define CONSOLE_VIDEO_CMDS \
"console {videodevice|videocodec|sendvideo" \
"|video_size|bitrate|fps|qmin" \
"|keypad|keypad_mask|keypad_entry" \
"|sdl_videodriver" \
"|device" \
"}"
#endif /* HAVE_VIDEO_CONSOLE and others */
struct video_desc; /* opaque type for video support */
struct video_desc *get_video_desc(struct ast_channel *c);
/* linked by console_video.o */
@ -32,18 +79,5 @@ int console_video_config(struct video_desc **penv, const char *var, const char *
void console_video_uninit(struct video_desc *env);
void console_video_start(struct video_desc *env, struct ast_channel *owner);
#ifdef HAVE_VIDEO_CONSOLE
#define CONSOLE_VIDEO_CMDS \
"console {videodevice|videocodec|sendvideo" \
"|video_size|bitrate|fps|qmin" \
"|keypad|keypad_mask|keypad_entry" \
"|sdl_videodriver" \
"|device" \
"}"
#else
#define CONSOLE_VIDEO_CMDS \
"console {device}"
#endif
#endif /* CONSOLE_VIDEO_H */
/* end of file */

View File

@ -3,6 +3,14 @@
* $Revision$
*/
#include "asterisk.h"
#include "console_video.h"
#include "asterisk/frame.h"
struct video_out_desc;
struct video_in_desc;
struct fbuf_t;
/*
* Each codec is defined by a number of callbacks
*/
@ -13,6 +21,7 @@ typedef int (*encoder_init_f)(AVCodecContext *v);
typedef int (*encoder_encode_f)(struct video_out_desc *v);
/*! \brief encapsulate the bistream in RTP frames */
/* struct fbuf_t, int mtu, struct ast_frame **tail */
typedef struct ast_frame *(*encoder_encap_f)(struct video_out_desc *out,
struct ast_frame **tail);
@ -953,7 +962,7 @@ struct _cm { /* map ffmpeg codec types to asterisk formats */
uint32_t ast_format; /* 0 is a terminator */
enum CodecID codec;
enum { CM_RD = 1, CM_WR = 2, CM_RDWR = 3 } rw; /* read or write or both ? */
struct video_codec_desc *codec_desc;
//struct video_codec_desc *codec_desc;
};
static struct _cm video_formats[] = {