1 /*****************************************************************************
2 * vout_xvideo.c: Xvideo video output display method
3 *****************************************************************************
4 * Copyright (C) 1998, 1999, 2000, 2001 VideoLAN
5 * $Id: vout_xvideo.c,v 1.3 2001/04/04 16:33:07 sam Exp $
7 * Authors: Shane Harper <shanegh@optusnet.com.au>
8 * Vincent Seguin <seguin@via.ecp.fr>
9 * Samuel Hocevar <sam@zoy.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 #define MODULE_NAME xvideo
27 #include "modules_inner.h"
29 /*****************************************************************************
31 *****************************************************************************/
34 #include <errno.h> /* ENOMEM */
35 #include <stdlib.h> /* free() */
36 #include <string.h> /* strerror() */
38 #ifdef HAVE_MACHINE_PARAM_H
40 #include <machine/param.h>
41 #include <sys/types.h> /* typedef ushort */
45 #include <sys/shm.h> /* shmget(), shmctl() */
47 #include <X11/Xutil.h>
48 #include <X11/keysym.h>
49 #include <X11/extensions/XShm.h>
50 #include <X11/extensions/Xv.h>
51 #include <X11/extensions/Xvlib.h>
61 #include "video_output.h"
63 #include "interface.h"
68 /*****************************************************************************
69 * vout_sys_t: video output X11 method descriptor
70 *****************************************************************************
71 * This structure is part of the video output thread descriptor.
72 * It describes the X11 specific properties of an output thread. X11 video
73 * output is performed through regular resizable windows. Windows can be
74 * dynamically resized to adapt to the size of the streams.
75 *****************************************************************************/
76 typedef struct vout_sys_s
80 /* this plugin (currently) requires the SHM Ext... */
81 boolean_t b_shm; /* shared memory extension flag */
84 /* Internal settings and properties */
85 Display * p_display; /* display pointer */
86 int i_screen; /* screen number */
87 Window window; /* root window */
88 GC gc; /* graphic context instance handler */
91 /* Display buffers and shared memory information */
92 /* Note: only 1 buffer (I don't know why the X11 plugin had 2.) */
94 XShmSegmentInfo shm_info; /* shared memory zone information */
96 /* X11 generic properties */
98 Atom wm_delete_window;
100 int i_width; /* width of main window */
101 int i_height; /* height of main window */
103 /* Screen saver properties */
104 int i_ss_timeout; /* timeout */
105 int i_ss_interval; /* interval between changes */
106 int i_ss_blanking; /* blanking mode */
107 int i_ss_exposure; /* exposure mode */
109 /* Mouse pointer properties */
110 boolean_t b_mouse; /* is the mouse pointer displayed ? */
114 /*****************************************************************************
116 *****************************************************************************/
117 static int vout_Probe ( probedata_t * );
118 static int vout_Create ( vout_thread_t * );
119 static int vout_Init ( vout_thread_t * );
120 static void vout_End ( vout_thread_t * );
121 static void vout_Destroy ( vout_thread_t * );
122 static int vout_Manage ( vout_thread_t * );
123 static void vout_Display ( vout_thread_t * );
124 static void vout_SetPalette( vout_thread_t *, u16 *, u16 *, u16 *, u16 * );
126 static int XVideoCreateWindow ( vout_thread_t * );
127 static int XVideoCreateShmImage ( vout_thread_t *, XvImage **,
128 XShmSegmentInfo *p_shm_info );
129 static void XVideoDestroyShmImage ( vout_thread_t *, XvImage *,
131 static void XVideoTogglePointer ( vout_thread_t * );
132 static void XVideoEnableScreenSaver ( vout_thread_t * );
133 static void XVideoDisableScreenSaver ( vout_thread_t * );
134 static void XVideoSetAttribute ( vout_thread_t *, char *, float );
136 static int XVideoCheckForXv ( Display * );
137 static int XVideoGetPort ( Display * );
138 static void XVideoOutputCoords ( const picture_t *, const boolean_t,
139 const int, const int,
140 int *, int *, int *, int * );
142 /*****************************************************************************
143 * Functions exported as capabilities. They are declared as static so that
144 * we don't pollute the namespace too much.
145 *****************************************************************************/
146 void _M( vout_getfunctions )( function_list_t * p_function_list )
148 p_function_list->pf_probe = vout_Probe;
149 p_function_list->functions.vout.pf_create = vout_Create;
150 p_function_list->functions.vout.pf_init = vout_Init;
151 p_function_list->functions.vout.pf_end = vout_End;
152 p_function_list->functions.vout.pf_destroy = vout_Destroy;
153 p_function_list->functions.vout.pf_manage = vout_Manage;
154 p_function_list->functions.vout.pf_display = vout_Display;
155 p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
158 /*****************************************************************************
159 * vout_Probe: probe the video driver and return a score
160 *****************************************************************************
161 * This returns a score to the plugin manager so that it can select the best
163 *****************************************************************************/
164 static int vout_Probe( probedata_t *p_data )
166 if( TestMethod( VOUT_METHOD_VAR, "xvideo" ) )
174 /*****************************************************************************
175 * vout_Create: allocate XVideo video thread output method
176 *****************************************************************************
177 * This function allocate and initialize a X11 vout method. It uses some of the
178 * vout properties to choose the window size, and change them according to the
179 * actual properties of the display.
180 *****************************************************************************/
181 static int vout_Create( vout_thread_t *p_vout )
185 /* Allocate structure */
186 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
187 if( p_vout->p_sys == NULL )
189 intf_ErrMsg( "vout error: %s", strerror(ENOMEM) );
193 /* Open display, unsing 'vlc_display' or DISPLAY environment variable */
194 psz_display = XDisplayName( main_GetPszVariable( VOUT_DISPLAY_VAR, NULL ) );
195 p_vout->p_sys->p_display = XOpenDisplay( psz_display );
197 if( p_vout->p_sys->p_display == NULL ) /* error */
199 intf_ErrMsg( "vout error: cannot open display %s", psz_display );
200 free( p_vout->p_sys );
203 p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
205 if( !XVideoCheckForXv( p_vout->p_sys->p_display ) )
207 intf_ErrMsg( "vout error: no XVideo extension" );
208 XCloseDisplay( p_vout->p_sys->p_display );
209 free( p_vout->p_sys );
213 /* Spawn base window - this window will include the video output window,
214 * but also command buttons, subtitles and other indicators */
215 if( XVideoCreateWindow( p_vout ) )
217 intf_ErrMsg( "vout error: cannot create XVideo window" );
218 XCloseDisplay( p_vout->p_sys->p_display );
219 free( p_vout->p_sys );
223 if( (p_vout->p_sys->xv_port = XVideoGetPort( p_vout->p_sys->p_display ))<0 )
226 /* XXX The brightness and contrast values should be read from environment
227 * XXX variables... */
228 XVideoSetAttribute( p_vout, "XV_BRIGHTNESS", 0.5 );
229 XVideoSetAttribute( p_vout, "XV_CONTRAST", 0.5 );
231 p_vout->p_sys->b_mouse = 1;
233 /* Disable screen saver and return */
234 XVideoDisableScreenSaver( p_vout );
239 /*****************************************************************************
240 * vout_Init: initialize XVideo video thread output method
241 *****************************************************************************
242 * This function creates the XvImage needed by the output thread. It is called
243 * at the beginning of the thread, but also each time the window is resized.
244 *****************************************************************************/
245 static int vout_Init( vout_thread_t *p_vout )
250 /* FIXME : As of 2001-03-16, XFree4 for MacOS X does not support Xshm. */
251 p_vout->p_sys->b_shm = 0;
254 /* Create XvImage using XShm extension */
255 i_err = XVideoCreateShmImage( p_vout, &p_vout->p_sys->p_xvimage,
256 &p_vout->p_sys->shm_info );
259 intf_Msg( "vout: XShm video extension unavailable" );
260 /* p_vout->p_sys->b_shm = 0; */
262 p_vout->b_need_render = 0;
264 /* Set bytes per line and initialize buffers */
265 p_vout->i_bytes_per_line =
266 (p_vout->p_sys->p_xvimage->data_size) /
267 (p_vout->p_sys->p_xvimage->height);
269 /* vout_SetBuffers( p_vout, p_vout->p_sys->p_xvimage[0]->data,
270 * p_vout->p_sys->p_xvimage[1]->data ); */
271 p_vout->p_buffer[0].i_pic_x = 0;
272 p_vout->p_buffer[0].i_pic_y = 0;
273 p_vout->p_buffer[0].i_pic_width = 0;
274 p_vout->p_buffer[0].i_pic_height = 0;
276 /* The first area covers all the screen */
277 p_vout->p_buffer[0].i_areas = 1;
278 p_vout->p_buffer[0].pi_area_begin[0] = 0;
279 p_vout->p_buffer[0].pi_area_end[0] = p_vout->i_height - 1;
282 p_vout->p_buffer[0].p_data = p_vout->p_sys->p_xvimage->data;
286 /*****************************************************************************
287 * vout_End: terminate XVideo video thread output method
288 *****************************************************************************
289 * Destroy the XVideo xImages created by vout_Init. It is called at the end of
290 * the thread, but also each time the window is resized.
291 *****************************************************************************/
292 static void vout_End( vout_thread_t *p_vout )
294 XVideoDestroyShmImage( p_vout, p_vout->p_sys->p_xvimage,
295 &p_vout->p_sys->shm_info );
298 /*****************************************************************************
299 * vout_Destroy: destroy XVideo video thread output method
300 *****************************************************************************
301 * Terminate an output method created by vout_CreateOutputMethod
302 *****************************************************************************/
303 static void vout_Destroy( vout_thread_t *p_vout )
305 /* Enable screen saver */
306 XVideoEnableScreenSaver( p_vout );
309 XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
310 XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
311 XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
313 XCloseDisplay( p_vout->p_sys->p_display );
315 /* Destroy structure */
316 free( p_vout->p_sys );
319 /*****************************************************************************
320 * vout_Manage: handle X11 events
321 *****************************************************************************
322 * This function should be called regularly by video output thread. It manages
323 * X11 events and allows window resizing. It returns a non null value on
326 * XXX Should "factor-out" common code in this and the "same" fn in the x11
328 *****************************************************************************/
329 static int vout_Manage( vout_thread_t *p_vout )
331 XEvent xevent; /* X11 event */
332 boolean_t b_resized; /* window has been resized */
333 char i_key; /* ISO Latin-1 key */
335 /* Handle X11 events: ConfigureNotify events are parsed to know if the
336 * output window's size changed, MapNotify and UnmapNotify to know if the
337 * window is mapped (and if the display is useful), and ClientMessages
338 * to intercept window destruction requests */
340 while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
341 StructureNotifyMask | KeyPressMask |
342 ButtonPressMask | ButtonReleaseMask, &xevent )
345 /* ConfigureNotify event: prepare */
346 if( (xevent.type == ConfigureNotify)
347 && ((xevent.xconfigure.width != p_vout->p_sys->i_width)
348 || (xevent.xconfigure.height != p_vout->p_sys->i_height)) )
350 /* Update dimensions */
353 p_vout->p_sys->i_width = xevent.xconfigure.width;
354 p_vout->p_sys->i_height = xevent.xconfigure.height;
357 /* MapNotify event: change window status and disable screen saver */
358 else if( xevent.type == MapNotify)
360 if( (p_vout != NULL) && !p_vout->b_active )
362 XVideoDisableScreenSaver( p_vout );
363 p_vout->b_active = 1;
366 /* UnmapNotify event: change window status and enable screen saver */
367 else if( xevent.type == UnmapNotify )
369 if( (p_vout != NULL) && p_vout->b_active )
371 XVideoEnableScreenSaver( p_vout );
372 p_vout->b_active = 0;
376 else if( xevent.type == KeyPress )
378 if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) )
380 /* FIXME: handle stuff here */
384 /* FIXME: need locking ! */
385 p_main->p_intf->b_die = 1;
391 else if( xevent.type == ButtonPress )
393 switch( ((XButtonEvent *)&xevent)->button )
396 /* in this part we will eventually manage
397 * clicks for DVD navigation for instance */
401 XVideoTogglePointer( p_vout );
406 else if( xevent.type == ButtonRelease )
408 switch( ((XButtonEvent *)&xevent)->button )
411 /* FIXME: need locking ! */
412 p_main->p_intf->b_menu_change = 1;
420 intf_DbgMsg( "%p -> unhandled event type %d received",
421 p_vout, xevent.type );
426 /* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
427 * are handled - according to the man pages, the format is always 32
429 while( XCheckTypedEvent( p_vout->p_sys->p_display,
430 ClientMessage, &xevent ) )
432 if( (xevent.xclient.message_type == p_vout->p_sys->wm_protocols)
433 && (xevent.xclient.data.l[0] == p_vout->p_sys->wm_delete_window ) )
435 p_main->p_intf->b_die = 1;
439 intf_DbgMsg( "%p -> unhandled ClientMessage received", p_vout );
443 if( (p_vout->i_width != p_vout->p_sys->i_width) ||
444 (p_vout->i_height != p_vout->p_sys->i_height) )
446 /* If video output size has changed, change interface window size */
447 intf_DbgMsg( "resizing output window" );
448 p_vout->p_sys->i_width = p_vout->i_width;
449 p_vout->p_sys->i_height = p_vout->i_height;
450 XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window,
451 p_vout->p_sys->i_width, p_vout->p_sys->i_height );
454 if( (p_vout->i_changes & VOUT_GRAYSCALE_CHANGE))
456 /* FIXME: clear flags ?? */
462 if( p_vout->i_changes & VOUT_SIZE_CHANGE )
464 intf_DbgMsg( "vout: resizing window" );
465 p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
468 XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window,
469 p_vout->i_width, p_vout->i_height );
471 /* Destroy XImages to change their size */
474 /* Recreate XImages. If SysInit failed, the thread cannot go on. */
475 if( vout_Init( p_vout ) )
477 intf_ErrMsg( "vout error: cannot resize display" );
481 intf_Msg( "vout: video display resized (%dx%d)",
482 p_vout->i_width, p_vout->i_height );
489 /*****************************************************************************
490 * vout_Display: displays previously rendered output
491 *****************************************************************************
492 * This function send the currently rendered image to X11 server, wait until
493 * it is displayed and switch the two rendering buffer, preparing next frame.
494 *****************************************************************************/
495 static void vout_Display( vout_thread_t *p_vout )
497 boolean_t b_draw = 1;
498 const int i_size = p_vout->i_width * p_vout->i_height;
500 switch( p_vout->p_rendered_pic->i_type )
502 case YUV_422_PICTURE:
503 intf_ErrMsg( "vout error: YUV_422_PICTURE not (yet) supported" );
507 case YUV_444_PICTURE:
508 intf_ErrMsg( "vout error: YUV_444_PICTURE not (yet) supported" );
512 case YUV_420_PICTURE:
513 memcpy( p_vout->p_sys->p_xvimage->data,
514 p_vout->p_rendered_pic->p_y, i_size );
515 memcpy( p_vout->p_sys->p_xvimage->data + ( i_size ),
516 p_vout->p_rendered_pic->p_v, i_size / 4 );
517 memcpy( p_vout->p_sys->p_xvimage->data + ( i_size ) + ( i_size / 4 ),
518 p_vout->p_rendered_pic->p_u, i_size / 4 );
524 int i_dummy, i_src_width, i_src_height,
525 i_dest_width, i_dest_height, i_dest_x, i_dest_y;
528 /* Could use p_vout->p_sys->i_width and p_vout->p_sys->i_height
529 *instead of calling XGetGeometry? */
530 XGetGeometry( p_vout->p_sys->p_display, p_vout->p_sys->window,
531 &window, &i_dummy, &i_dummy,
532 &i_src_width, &i_src_height, &i_dummy, &i_dummy );
534 XVideoOutputCoords( p_vout->p_rendered_pic, p_vout->b_scale,
535 i_src_width, i_src_height, &i_dest_x, &i_dest_y,
536 &i_dest_width, &i_dest_height);
538 XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->xv_port,
539 p_vout->p_sys->window, p_vout->p_sys->gc,
540 p_vout->p_sys->p_xvimage,
541 0 /*src_x*/, 0 /*src_y*/,
542 p_vout->p_rendered_pic->i_width,
543 p_vout->p_rendered_pic->i_height,
544 i_dest_x, i_dest_y, i_dest_width, i_dest_height,
549 static void vout_SetPalette( p_vout_thread_t p_vout,
550 u16 *red, u16 *green, u16 *blue, u16 *transp )
555 /* following functions are local */
557 /*****************************************************************************
558 * XVideoCheckForXv: check for the XVideo extension
559 *****************************************************************************/
560 static int XVideoCheckForXv( Display *dpy )
564 switch( XvQueryExtension( dpy, &i, &i, &i, &i, &i ) )
570 intf_ErrMsg( "vout error: XvBadExtension" );
574 intf_ErrMsg( "vout error: XvBadAlloc" );
578 intf_ErrMsg( "vout error: XvQueryExtension failed" );
583 /*****************************************************************************
584 * XVideoCreateWindow: open and set-up XVideo main window
585 *****************************************************************************/
586 static int XVideoCreateWindow( vout_thread_t *p_vout )
588 XSizeHints xsize_hints;
589 XSetWindowAttributes xwindow_attributes;
593 boolean_t b_configure_notify;
594 boolean_t b_map_notify;
596 /* Set main window's size */
597 p_vout->p_sys->i_width = main_GetIntVariable( VOUT_WIDTH_VAR,
598 VOUT_WIDTH_DEFAULT );
599 p_vout->p_sys->i_height = main_GetIntVariable( VOUT_HEIGHT_VAR,
600 VOUT_HEIGHT_DEFAULT );
602 /* Prepare window manager hints and properties */
603 xsize_hints.base_width = p_vout->p_sys->i_width;
604 xsize_hints.base_height = p_vout->p_sys->i_height;
605 xsize_hints.flags = PSize;
606 p_vout->p_sys->wm_protocols = XInternAtom( p_vout->p_sys->p_display,
607 "WM_PROTOCOLS", True );
608 p_vout->p_sys->wm_delete_window = XInternAtom( p_vout->p_sys->p_display,
609 "WM_DELETE_WINDOW", True );
611 /* Prepare window attributes */
612 xwindow_attributes.backing_store = Always; /* save the hidden part */
613 xwindow_attributes.background_pixel = WhitePixel( p_vout->p_sys->p_display,
614 p_vout->p_sys->i_screen );
616 xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
618 /* Create the window and set hints - the window must receive ConfigureNotify
619 * events, and, until it is displayed, Expose and MapNotify events. */
620 p_vout->p_sys->window =
621 XCreateWindow( p_vout->p_sys->p_display,
622 DefaultRootWindow( p_vout->p_sys->p_display ),
624 p_vout->p_sys->i_width, p_vout->p_sys->i_height, 1,
626 CWBackingStore | CWBackPixel | CWEventMask,
627 &xwindow_attributes );
629 /* Set window manager hints and properties: size hints, command,
630 * window's name, and accepted protocols */
631 XSetWMNormalHints( p_vout->p_sys->p_display, p_vout->p_sys->window,
633 XSetCommand( p_vout->p_sys->p_display, p_vout->p_sys->window,
634 p_main->ppsz_argv, p_main->i_argc );
635 XStoreName( p_vout->p_sys->p_display, p_vout->p_sys->window,
636 VOUT_TITLE " (XVideo output)" );
638 if( (p_vout->p_sys->wm_protocols == None) /* use WM_DELETE_WINDOW */
639 || (p_vout->p_sys->wm_delete_window == None)
640 || !XSetWMProtocols( p_vout->p_sys->p_display, p_vout->p_sys->window,
641 &p_vout->p_sys->wm_delete_window, 1 ) )
643 /* WM_DELETE_WINDOW is not supported by window manager */
644 intf_Msg( "vout error: missing or bad window manager" );
647 /* Creation of a graphic context that doesn't generate a GraphicsExpose
648 * event when using functions like XCopyArea */
649 xgcvalues.graphics_exposures = False;
650 p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display,
651 p_vout->p_sys->window,
652 GCGraphicsExposures, &xgcvalues);
654 /* Send orders to server, and wait until window is displayed - three
655 * events must be received: a MapNotify event, an Expose event allowing
656 * drawing in the window, and a ConfigureNotify to get the window
657 * dimensions. Once those events have been received, only ConfigureNotify
658 * events need to be received. */
660 b_configure_notify = 0;
662 XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
665 XNextEvent( p_vout->p_sys->p_display, &xevent);
666 if( (xevent.type == Expose)
667 && (xevent.xexpose.window == p_vout->p_sys->window) )
671 else if( (xevent.type == MapNotify)
672 && (xevent.xmap.window == p_vout->p_sys->window) )
676 else if( (xevent.type == ConfigureNotify)
677 && (xevent.xconfigure.window == p_vout->p_sys->window) )
679 b_configure_notify = 1;
680 p_vout->p_sys->i_width = xevent.xconfigure.width;
681 p_vout->p_sys->i_height = xevent.xconfigure.height;
683 } while( !( b_expose && b_configure_notify && b_map_notify ) );
685 XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
686 StructureNotifyMask | KeyPressMask |
687 ButtonPressMask | ButtonReleaseMask );
689 /* At this stage, the window is open, displayed, and ready to
694 /*****************************************************************************
695 * XVideoCreateShmImage: create an XvImage using shared memory extension
696 *****************************************************************************
697 * Prepare an XvImage for display function.
698 * The order of the operations respects the recommandations of the mit-shm
699 * document by J.Corbet and K.Packard. Most of the parameters were copied from
701 *****************************************************************************/
702 static int XVideoCreateShmImage( vout_thread_t *p_vout, XvImage **pp_xvimage,
703 XShmSegmentInfo *p_shm_info)
705 #define GUID_YUV12_PLANAR 0x32315659
707 *pp_xvimage = XvShmCreateImage( p_vout->p_sys->p_display,
708 p_vout->p_sys->xv_port,
709 GUID_YUV12_PLANAR, 0,
710 p_vout->i_width, p_vout->i_height,
713 p_shm_info->shmid = shmget( IPC_PRIVATE, (*pp_xvimage)->data_size,
715 p_shm_info->shmaddr = (*pp_xvimage)->data = shmat( p_shm_info->shmid,
717 p_shm_info->readOnly = False;
719 shmctl( p_shm_info->shmid, IPC_RMID, 0 ); /* XXX */
721 if( !XShmAttach(p_vout->p_sys->p_display, p_shm_info) )
723 intf_ErrMsg( "vout error: XShmAttach failed" );
727 /* Send image to X server. This instruction is required, since having
728 * built a Shm XImage and not using it causes an error on XCloseDisplay */
729 XFlush( p_vout->p_sys->p_display );
734 /*****************************************************************************
735 * XVideoDestroyShmImage
736 *****************************************************************************
737 * Destroy XImage AND associated data. Detach shared memory segment from
738 * server and process, then free it. If pointer is NULL, the image won't be
739 * destroyed (see vout_ManageOutputMethod())
740 *****************************************************************************/
741 static void XVideoDestroyShmImage( vout_thread_t *p_vout, XvImage *p_xvimage,
742 XShmSegmentInfo *p_shm_info )
744 /* If pointer is NULL, do nothing */
745 if( p_xvimage == NULL )
750 XShmDetach( p_vout->p_sys->p_display, p_shm_info );/* detach from server */
752 XDestroyImage( p_ximage );
754 /* XvDestroyImage( p_xvimage ); XXX */
757 if( shmdt( p_shm_info->shmaddr ) ) /* detach shared memory from process */
758 { /* also automatic freeing... */
759 intf_ErrMsg( "vout error: cannot detach shared memory (%s)",
764 /*****************************************************************************
765 * XVideoEnableScreenSaver: enable screen saver
766 *****************************************************************************
767 * This function enable the screen saver on a display after it had been
768 * disabled by XDisableScreenSaver. Both functions use a counter mechanism to
769 * know wether the screen saver can be activated or not: if n successive calls
770 * are made to XDisableScreenSaver, n successive calls to XEnableScreenSaver
771 * will be required before the screen saver could effectively be activated.
772 *****************************************************************************/
773 void XVideoEnableScreenSaver( vout_thread_t *p_vout )
775 intf_DbgMsg( "intf: enabling screen saver" );
776 XSetScreenSaver( p_vout->p_sys->p_display, p_vout->p_sys->i_ss_timeout,
777 p_vout->p_sys->i_ss_interval,
778 p_vout->p_sys->i_ss_blanking,
779 p_vout->p_sys->i_ss_exposure );
782 /*****************************************************************************
783 * XVideoDisableScreenSaver: disable screen saver
784 *****************************************************************************
785 * See XEnableScreenSaver
786 *****************************************************************************/
787 void XVideoDisableScreenSaver( vout_thread_t *p_vout )
789 /* Save screen saver informations */
790 XGetScreenSaver( p_vout->p_sys->p_display, &p_vout->p_sys->i_ss_timeout,
791 &p_vout->p_sys->i_ss_interval,
792 &p_vout->p_sys->i_ss_blanking,
793 &p_vout->p_sys->i_ss_exposure );
795 /* Disable screen saver */
796 intf_DbgMsg( "intf: disabling screen saver" );
797 XSetScreenSaver( p_vout->p_sys->p_display, 0,
798 p_vout->p_sys->i_ss_interval,
799 p_vout->p_sys->i_ss_blanking,
800 p_vout->p_sys->i_ss_exposure );
803 /*****************************************************************************
804 * XVideoTogglePointer: hide or show the mouse pointer
805 *****************************************************************************
806 * This function hides the X pointer if it is visible by putting it at
807 * coordinates (32,32) and setting the pointer sprite to a blank one. To
808 * show it again, we disable the sprite and restore the original coordinates.
809 *****************************************************************************/
810 void XVideoTogglePointer( vout_thread_t *p_vout )
812 static Cursor cursor;
813 static boolean_t b_cursor = 0;
815 if( p_vout->p_sys->b_mouse )
817 p_vout->p_sys->b_mouse = 0;
822 Pixmap blank = XCreatePixmap( p_vout->p_sys->p_display,
823 DefaultRootWindow(p_vout->p_sys->p_display),
826 XParseColor( p_vout->p_sys->p_display,
827 XCreateColormap( p_vout->p_sys->p_display,
829 p_vout->p_sys->p_display ),
831 p_vout->p_sys->p_display,
832 p_vout->p_sys->i_screen ),
836 cursor = XCreatePixmapCursor( p_vout->p_sys->p_display,
837 blank, blank, &color, &color, 1, 1 );
841 XDefineCursor( p_vout->p_sys->p_display,
842 p_vout->p_sys->window, cursor );
846 p_vout->p_sys->b_mouse = 1;
848 XUndefineCursor( p_vout->p_sys->p_display, p_vout->p_sys->window );
852 /* This based on some code in SetBufferPicture... At the moment it's only
853 * used by the xvideo plugin, but others may want to use it. */
854 static void XVideoOutputCoords( const picture_t *p_pic, const boolean_t scale,
855 const int win_w, const int win_h,
856 int *dx, int *dy, int *w, int *h)
860 *w = p_pic->i_width; *h = p_pic->i_height;
865 switch( p_pic->i_aspect_ratio )
867 case AR_3_4_PICTURE: *h = win_w * 3 / 4; break;
868 case AR_16_9_PICTURE: *h = win_w * 9 / 16; break;
869 case AR_221_1_PICTURE: *h = win_w * 100 / 221; break;
870 case AR_SQUARE_PICTURE:
871 default: *h = win_w; break;
877 switch( p_pic->i_aspect_ratio )
879 case AR_3_4_PICTURE: *w = win_h * 4 / 3; break;
880 case AR_16_9_PICTURE: *w = win_h * 16 / 9; break;
881 case AR_221_1_PICTURE: *w = win_h * 221 / 100; break;
882 case AR_SQUARE_PICTURE:
883 default: *w = win_h; break;
888 /* Set picture position */
889 *dx = (win_w - *w) / 2;
890 *dy = (win_h - *h) / 2;
894 static int XVideoGetPort( Display *dpy )
897 XvAdaptorInfo *adaptor_info;
899 switch( XvQueryAdaptors( dpy, DefaultRootWindow( dpy ),
900 &i_adaptors, &adaptor_info ) )
906 intf_ErrMsg( "vout error: XvBadExtension for XvQueryAdaptors" );
910 intf_ErrMsg( "vout error: XvBadAlloc for XvQueryAdaptors" );
914 intf_ErrMsg( "vout error: XvQueryAdaptors failed" );
918 for( i=0; i < i_adaptors; ++i )
919 if( ( adaptor_info[ i ].type & XvInputMask ) &&
920 ( adaptor_info[ i ].type & XvImageMask ) )
922 return adaptor_info[ i ].base_id;
925 intf_ErrMsg( "vout error: didn't find an Xvideo image input port." );
930 /*****************************************************************************
932 *****************************************************************************
933 * This function can be used to set attributes, e.g. XV_BRIGHTNESS and
934 * XV_CONTRAST. "value" should be in the range of 0 to 1.
935 *****************************************************************************/
936 static void XVideoSetAttribute( vout_thread_t *p_vout,
937 char *attr_name, float f_value )
940 XvAttribute *p_attrib;
941 Display *p_dpy = p_vout->p_sys->p_display;
942 int xv_port = p_vout->p_sys->xv_port;
944 p_attrib = XvQueryPortAttributes( p_dpy, xv_port, &i_attrib );
950 if( !strcmp( p_attrib[ i_attrib ].name, attr_name ) )
952 int i_sv = f_value * ( p_attrib[ i_attrib ].max_value
953 - p_attrib[ i_attrib ].min_value + 1 )
954 + p_attrib[ i_attrib ].min_value;
956 XvSetPortAttribute( p_dpy, xv_port,
957 XInternAtom( p_dpy, attr_name, False ), i_sv );
961 } while( i_attrib > 0 );