2 XOver a general x11 vo for mplayer overlay drivers based on :
3 VIDIX accelerated overlay in a X window
5 (C) Alex Beregszaszi & Zoltan Ponekker & Nick Kurshev
7 WS window manager by Pontscho/Fresh!
9 Based on vo_gl.c and vo_vesa.c and vo_xmga.c (.so mastah! ;))
20 #include "video_out.h"
21 #include "video_out_internal.h"
24 #include <X11/Xutil.h>
25 //#include <X11/keysym.h>
27 #ifdef CONFIG_XINERAMA
28 #include <X11/extensions/Xinerama.h>
31 #include "x11_common.h"
36 #include "gui/interface.h"
40 static const vo_info_t info
=
42 "General X11 driver for overlay capable video output drivers",
50 #define UNUSED(x) ((void)(x)) /* Removes warning about unused arguments */
52 /* X11 related variables */
53 /* Colorkey handling */
56 /* Image parameters */
57 static uint32_t image_width
;
58 static uint32_t image_height
;
59 static uint32_t image_format
;
61 /* Window parameters */
62 static uint32_t window_x
, window_y
;
63 static uint32_t window_width
, window_height
;
65 /* used by XGetGeometry & XTranslateCoordinates for moving/resizing window */
66 static uint32_t drwX
, drwY
, drwWidth
, drwHeight
, drwBorderWidth
,
67 drwDepth
, drwcX
, drwcY
, dwidth
, dheight
;
69 static const vo_functions_t
* sub_vo
= NULL
;
72 static void set_window(int force_update
)
77 XGetGeometry(mDisplay
, vo_window
, &mRoot
, &drwX
, &drwY
, &drwWidth
,
78 &drwHeight
, &drwBorderWidth
, &drwDepth
);
81 XTranslateCoordinates(mDisplay
, vo_window
, mRoot
, 0, 0,
82 &drwcX
, &drwcY
, &mRoot
);
83 aspect(&dwidth
,&dheight
,A_NOZOOM
);
85 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",
86 drwcX
, drwcY
, drwX
, drwY
, drwWidth
, drwHeight
);
88 /* following stuff copied from vo_xmga.c */
92 aspect(&dwidth
,&dheight
,A_NOZOOM
);
93 drwcX
=drwX
=vo_dx
; drwcY
=drwY
=vo_dy
; drwWidth
=vo_dwidth
; drwHeight
=vo_dheight
;
99 aspect(&dwidth
,&dheight
,A_ZOOM
);
100 drwX
= (vo_screenwidth
- ((int)dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
)) / 2;
102 drwY
= (vo_screenheight
- ((int)dheight
> vo_screenheight
? vo_screenheight
: dheight
)) / 2;
104 drwWidth
= ((int)dwidth
> vo_screenwidth
? vo_screenwidth
: dwidth
);
105 drwHeight
= ((int)dheight
> vo_screenheight
? vo_screenheight
: dheight
);
106 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix-fs] dcx: %d dcy: %d dx: %d dy: %d dw: %d dh: %d\n",
107 drwcX
, drwcY
, drwX
, drwY
, drwWidth
, drwHeight
);
111 vo_dwidth
=drwWidth
; vo_dheight
=drwHeight
;
113 #ifdef CONFIG_XINERAMA
114 if (XineramaIsActive(mDisplay
))
116 XineramaScreenInfo
*screens
;
120 screens
= XineramaQueryScreens(mDisplay
, &num_screens
);
122 /* find the screen we are on */
123 while (i
<num_screens
&&
124 ((screens
[i
].x_org
< (int)drwcX
) ||
125 (screens
[i
].y_org
< (int)drwcY
) ||
126 (screens
[i
].x_org
+ screens
[i
].width
>= (int)drwcX
) ||
127 (screens
[i
].y_org
+ screens
[i
].height
>= (int)drwcY
)))
134 /* save the screen we are on */
137 /* oops.. couldnt find the screen we are on
138 * because the upper left corner left the
139 * visual range. assume we are still on the
145 /* set drwcX and drwcY to the right values */
146 drwcX
= drwcX
- screens
[i
].x_org
;
147 drwcY
= drwcY
- screens
[i
].y_org
;
152 if ( vo_panscan
> 0.0f
&& vo_fs
)
154 drwcX
-=vo_panscan_x
>> 1;
155 drwcY
-=vo_panscan_y
>> 1;
156 drwX
-=vo_panscan_x
>> 1;
157 drwY
-=vo_panscan_y
>> 1;
158 drwWidth
+=vo_panscan_x
;
159 drwHeight
+=vo_panscan_y
;
162 /* set new values in VIDIX */
163 if (force_update
|| (window_x
!= drwcX
) || (window_y
!= drwcY
) ||
164 (window_width
!= drwWidth
) || (window_height
!= drwHeight
))
167 // do a backup of window coordinates
168 w
.x
= window_x
= drwcX
;
169 w
.y
= window_y
= drwcY
;
172 w
.w
= window_width
= drwWidth
;
173 w
.h
= window_height
= drwHeight
;
175 if(sub_vo
->control(VOCTRL_XOVERLAY_SET_WIN
,&w
) != VO_TRUE
)
176 mp_msg(MSGT_VO
, MSGL_ERR
, "xvidx: set_overlay failed\n");
178 mp_msg(MSGT_VO
, MSGL_V
, "[xvidix] window properties: pos: %dx%d, size: %dx%d\n", vo_dx
, vo_dy
, window_width
, window_height
);
183 /* fill drawable with specified color */
184 XSetBackground(mDisplay
, vo_gc
, 0L);
185 XClearWindow( mDisplay
,vo_window
);
186 XSetForeground(mDisplay
, vo_gc
, colorkey
);
187 XFillRectangle(mDisplay
, vo_window
, vo_gc
, drwX
, drwY
, drwWidth
,
188 (vo_fs
? drwHeight
- 1 : drwHeight
));
190 /* flush, update drawable */
196 /* connect to server, create and map window,
197 * allocate colors and (shared) memory
199 static int config(uint32_t width
, uint32_t height
, uint32_t d_width
,
200 uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
204 XSetWindowAttributes xswa
;
205 unsigned long xswamask
;
206 XWindowAttributes attribs
;
207 int window_depth
, r
, g
, b
;
208 mp_colorkey_t colork
;
211 sprintf(_title
,"MPlayer %s X11 Overlay",sub_vo
->info
->name
);
216 image_height
= height
;
218 image_format
= format
;
220 aspect_save_orig(width
, height
);
221 aspect_save_prescale(d_width
, d_height
);
222 update_xinerama_info();
224 window_width
= d_width
;
225 window_height
= d_height
;
227 r
= (vo_colorkey
& 0x00ff0000) >> 16;
228 g
= (vo_colorkey
& 0x0000ff00) >> 8;
229 b
= vo_colorkey
& 0x000000ff;
230 switch(vo_depthonscreen
)
233 colorkey
= vo_colorkey
;
236 colorkey
= vo_colorkey
& 0x00ffffff;
239 colorkey
= ((r
>> 3) << 11) | ((g
>> 2) << 5) | (b
>> 3);
242 colorkey
= ((r
>> 3) << 10) | ((g
>> 3) << 5) | (b
>> 3);
245 mp_msg(MSGT_VO
, MSGL_ERR
, "Sorry, this (%d) color depth is not supported\n",
248 mp_msg(MSGT_VO
, MSGL_V
, "Using colorkey: %x\n", colorkey
);
250 aspect(&d_width
, &d_height
, A_NOZOOM
);
252 vo_dx
=( vo_screenwidth
- d_width
) / 2; vo_dy
=( vo_screenheight
- d_height
) / 2;
255 vo_dwidth
=d_width
; vo_dheight
=d_height
;
258 if(use_gui
) guiGetEvent( guiSetShVideo
,0 ); // the GUI will set up / resize the window
263 #ifdef X11_FULLSCREEN
264 if ( ( flags
&VOFLAG_FULLSCREEN
)||(flags
& VOFLAG_SWSCALE
) ) aspect(&d_width
, &d_height
, A_ZOOM
);
268 /* Make the window */
269 XGetWindowAttributes(mDisplay
, DefaultRootWindow(mDisplay
), &attribs
);
272 window_depth
= attribs
.depth
;
273 if ((window_depth
!= 15) && (window_depth
!= 16) && (window_depth
!= 24)
274 && (window_depth
!= 32))
276 XMatchVisualInfo(mDisplay
, mScreen
, window_depth
, TrueColor
, &vinfo
);
278 xswa
.background_pixel
= BlackPixel(mDisplay
, mScreen
);
279 xswa
.border_pixel
= 0;
280 xswa
.colormap
= XCreateColormap(mDisplay
, RootWindow(mDisplay
, mScreen
),
281 vinfo
.visual
, AllocNone
);
282 xswamask
= CWBackPixel
| CWBorderPixel
| CWColormap
;
284 vo_x11_create_vo_window(&vinfo
, vo_dx
, vo_dy
,
285 window_width
, window_height
, flags
,
286 xswa
.colormap
, "xvidix", title
);
287 XChangeWindowAttributes(mDisplay
, vo_window
, xswamask
, &xswa
);
293 if ( ( !WinID
)&&( flags
&VOFLAG_FULLSCREEN
) ) { vo_dx
=0; vo_dy
=0; vo_dwidth
=vo_screenwidth
; vo_dheight
=vo_screenheight
; vo_fs
=1; }
295 if(sub_vo
->config(image_width
,image_height
,vo_dwidth
,vo_dheight
,
296 flags
| VOFLAG_XOVERLAY_SUB_VO
,NULL
,format
)) {
297 mp_msg(MSGT_VO
, MSGL_ERR
, "xover: sub vo config failed\n");
300 colork
.x11
= colorkey
;
304 if(sub_vo
->control(VOCTRL_XOVERLAY_SET_COLORKEY
,&colork
) != VO_TRUE
)
305 mp_msg(MSGT_VO
, MSGL_WARN
, "xover: set_colorkey failed\n");
309 XSync(mDisplay
, False
);
316 static void check_events(void)
318 const int event
= vo_x11_check_events(mDisplay
);
320 if ((event
& VO_EVENT_RESIZE
) || (event
& VO_EVENT_EXPOSE
))
322 sub_vo
->check_events();
326 /* draw_osd, flip_page, draw_slice, draw_frame should be
327 overwritten with vidix functions (vosub_vidix.c) */
328 static void draw_osd(void)
330 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_osd!\n");
333 static void flip_page(void)
335 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo flip_page!\n");
338 static int draw_slice(uint8_t *src
[], int stride
[],
339 int w
, int h
, int x
, int y
)
347 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_slice!\n");
351 static int draw_frame(uint8_t *src
[])
354 mp_msg(MSGT_VO
, MSGL_FATAL
, "xover error: didn't used sub vo draw_frame!\n");
358 static void uninit(void)
360 if(!vo_config_count
) return;
361 if(sub_vo
) sub_vo
->uninit();
364 // Restore our callbacks
365 video_out_xover
.draw_frame
= draw_frame
;
366 video_out_xover
.draw_slice
= draw_slice
;
367 video_out_xover
.flip_page
= flip_page
;
368 video_out_xover
.draw_osd
= draw_osd
;
371 static int preinit(const char *arg
)
376 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay need a subdriver\n");
380 for(i
= 0 ; video_out_drivers
[i
] != NULL
; i
++) {
381 if(!strcmp(video_out_drivers
[i
]->info
->short_name
,arg
) &&
382 strcmp(video_out_drivers
[i
]->info
->short_name
,"xover"))
385 if(!video_out_drivers
[i
]) {
386 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: Subdriver %s not found\n", arg
);
389 if(video_out_drivers
[i
]->control(VOCTRL_XOVERLAY_SUPPORT
,NULL
) != VO_TRUE
) {
390 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: %s doesn't support XOverlay\n", arg
);
394 if (!vo_init()) return VO_FALSE
;
395 if(video_out_drivers
[i
]->preinit(NULL
)) {
396 mp_msg(MSGT_VO
, MSGL_ERR
, "VO XOverlay: Subvo init failed\n");
399 sub_vo
= video_out_drivers
[i
];
400 // Setup the sub vo callbacks
401 video_out_xover
.draw_frame
= sub_vo
->draw_frame
;
402 video_out_xover
.draw_slice
= sub_vo
->draw_slice
;
403 video_out_xover
.flip_page
= sub_vo
->flip_page
;
404 video_out_xover
.draw_osd
= sub_vo
->draw_osd
;
408 static int control(uint32_t request
, void *data
, ...)
410 if(!sub_vo
) return VO_ERROR
;
412 case VOCTRL_GUISUPPORT
:
414 case VOCTRL_GET_PANSCAN
:
415 if ( !vo_config_count
|| !vo_fs
) return VO_FALSE
;
420 case VOCTRL_FULLSCREEN
:
422 case VOCTRL_SET_PANSCAN
:
423 if ( vo_fs
&& ( vo_panscan
!= vo_panscan_amount
) )
430 // Safe atm bcs nothing use more than 1 arg
431 return sub_vo
->control(request
,data
);