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.1 2001/04/01 06:21:44 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 * );
135 static int XVideoCheckForXv ( Display * );
136 static void XVideoOutputCoords ( const picture_t *, const boolean_t,
137 const int, const int,
138 int *, int *, int *, int * );
140 /*****************************************************************************
141 * Functions exported as capabilities. They are declared as static so that
142 * we don't pollute the namespace too much.
143 *****************************************************************************/
144 void _M( vout_getfunctions )( function_list_t * p_function_list )
146 p_function_list->pf_probe = vout_Probe;
147 p_function_list->functions.vout.pf_create = vout_Create;
148 p_function_list->functions.vout.pf_init = vout_Init;
149 p_function_list->functions.vout.pf_end = vout_End;
150 p_function_list->functions.vout.pf_destroy = vout_Destroy;
151 p_function_list->functions.vout.pf_manage = vout_Manage;
152 p_function_list->functions.vout.pf_display = vout_Display;
153 p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
156 /*****************************************************************************
157 * vout_Probe: probe the video driver and return a score
158 *****************************************************************************
159 * This returns a score to the plugin manager so that it can select the best
161 *****************************************************************************/
162 static int vout_Probe( probedata_t *p_data )
164 if( TestMethod( VOUT_METHOD_VAR, "xvideo" ) )
172 /*****************************************************************************
173 * vout_Create: allocate XVideo video thread output method
174 *****************************************************************************
175 * This function allocate and initialize a X11 vout method. It uses some of the
176 * vout properties to choose the window size, and change them according to the
177 * actual properties of the display.
178 *****************************************************************************/
179 static int vout_Create( vout_thread_t *p_vout )
183 /* Allocate structure */
184 p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
185 if( p_vout->p_sys == NULL )
187 intf_ErrMsg( "vout error: %s", strerror(ENOMEM) );
191 /* Open display, unsing 'vlc_display' or DISPLAY environment variable */
192 psz_display = XDisplayName( main_GetPszVariable( VOUT_DISPLAY_VAR, NULL ) );
193 p_vout->p_sys->p_display = XOpenDisplay( psz_display );
195 if( p_vout->p_sys->p_display == NULL ) /* error */
197 intf_ErrMsg( "vout error: cannot open display %s", psz_display );
198 free( p_vout->p_sys );
201 p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
203 if( !XVideoCheckForXv( p_vout->p_sys->p_display ) )
205 intf_ErrMsg( "vout error: no XVideo extension" );
206 XCloseDisplay( p_vout->p_sys->p_display );
207 free( p_vout->p_sys );
211 /* Spawn base window - this window will include the video output window,
212 * but also command buttons, subtitles and other indicators */
213 if( XVideoCreateWindow( p_vout ) )
215 intf_ErrMsg( "vout error: cannot create XVideo window" );
216 XCloseDisplay( p_vout->p_sys->p_display );
217 free( p_vout->p_sys );
221 p_vout->p_sys->b_mouse = 1;
223 /* Disable screen saver and return */
224 XVideoDisableScreenSaver( p_vout );
229 /*****************************************************************************
230 * vout_Init: initialize XVideo video thread output method
231 *****************************************************************************
232 * This function create the XImages needed by the output thread. It is called
233 * at the beginning of the thread, but also each time the window is resized.
234 *****************************************************************************/
235 static int vout_Init( vout_thread_t *p_vout )
240 /* FIXME : As of 2001-03-16, XFree4 for MacOS X does not support Xshm. */
241 p_vout->p_sys->b_shm = 0;
244 /* Create XImages using XShm extension */
245 i_err = XVideoCreateShmImage( p_vout, &p_vout->p_sys->p_xvimage,
246 &p_vout->p_sys->shm_info );
249 intf_Msg( "vout: XShm video extension unavailable" );
250 /* p_vout->p_sys->b_shm = 0; */
252 p_vout->b_need_render = 0; /* = 1 if not using Xv extension. */
254 /* Set bytes per line and initialize buffers */
255 p_vout->i_bytes_per_line =
256 (p_vout->p_sys->p_xvimage->data_size) /
257 (p_vout->p_sys->p_xvimage->height);
259 /* vout_SetBuffers( p_vout, p_vout->p_sys->p_xvimage[0]->data,
260 * p_vout->p_sys->p_xvimage[1]->data ); */
261 p_vout->p_buffer[0].i_pic_x = 0;
262 p_vout->p_buffer[0].i_pic_y = 0;
263 p_vout->p_buffer[0].i_pic_width = 0;
264 p_vout->p_buffer[0].i_pic_height = 0;
266 /* The first area covers all the screen */
267 p_vout->p_buffer[0].i_areas = 1;
268 p_vout->p_buffer[0].pi_area_begin[0] = 0;
269 p_vout->p_buffer[0].pi_area_end[0] = p_vout->i_height - 1;
272 p_vout->p_buffer[0].p_data = p_vout->p_sys->p_xvimage->data;
276 /*****************************************************************************
277 * vout_End: terminate XVideo video thread output method
278 *****************************************************************************
279 * Destroy the XVideo xImages created by vout_Init. It is called at the end of
280 * the thread, but also each time the window is resized.
281 *****************************************************************************/
282 static void vout_End( vout_thread_t *p_vout )
284 XVideoDestroyShmImage( p_vout, p_vout->p_sys->p_xvimage,
285 &p_vout->p_sys->shm_info );
288 /*****************************************************************************
289 * vout_Destroy: destroy XVideo video thread output method
290 *****************************************************************************
291 * Terminate an output method created by vout_CreateOutputMethod
292 *****************************************************************************/
293 static void vout_Destroy( vout_thread_t *p_vout )
295 /* Enable screen saver */
296 XVideoEnableScreenSaver( p_vout );
299 XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
300 XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
301 XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
303 XCloseDisplay( p_vout->p_sys->p_display );
305 /* Destroy structure */
306 free( p_vout->p_sys );
309 /*****************************************************************************
310 * vout_Manage: handle X11 events
311 *****************************************************************************
312 * This function should be called regularly by video output thread. It manages
313 * X11 events and allows window resizing. It returns a non null value on
316 * XXX Should "factor-out" common code in this and the "same" fn in the x11
318 *****************************************************************************/
319 static int vout_Manage( vout_thread_t *p_vout )
321 XEvent xevent; /* X11 event */
322 boolean_t b_resized; /* window has been resized */
323 char i_key; /* ISO Latin-1 key */
325 /* Handle X11 events: ConfigureNotify events are parsed to know if the
326 * output window's size changed, MapNotify and UnmapNotify to know if the
327 * window is mapped (and if the display is useful), and ClientMessages
328 * to intercept window destruction requests */
330 while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
331 StructureNotifyMask | KeyPressMask |
332 ButtonPressMask | ButtonReleaseMask, &xevent )
335 /* ConfigureNotify event: prepare */
336 if( (xevent.type == ConfigureNotify)
337 && ((xevent.xconfigure.width != p_vout->p_sys->i_width)
338 || (xevent.xconfigure.height != p_vout->p_sys->i_height)) )
340 /* Update dimensions */
343 p_vout->p_sys->i_width = xevent.xconfigure.width;
344 p_vout->p_sys->i_height = xevent.xconfigure.height;
347 /* MapNotify event: change window status and disable screen saver */
348 else if( xevent.type == MapNotify)
350 if( (p_vout != NULL) && !p_vout->b_active )
352 XVideoDisableScreenSaver( p_vout );
353 p_vout->b_active = 1;
356 /* UnmapNotify event: change window status and enable screen saver */
357 else if( xevent.type == UnmapNotify )
359 if( (p_vout != NULL) && p_vout->b_active )
361 XVideoEnableScreenSaver( p_vout );
362 p_vout->b_active = 0;
366 else if( xevent.type == KeyPress )
368 if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) )
370 /* FIXME: handle stuff here */
374 /* FIXME: need locking ! */
375 p_main->p_intf->b_die = 1;
381 else if( xevent.type == ButtonPress )
383 switch( ((XButtonEvent *)&xevent)->button )
386 /* in this part we will eventually manage
387 * clicks for DVD navigation for instance */
391 XVideoTogglePointer( p_vout );
396 else if( xevent.type == ButtonRelease )
398 switch( ((XButtonEvent *)&xevent)->button )
401 /* FIXME: need locking ! */
402 p_main->p_intf->b_menu_change = 1;
410 intf_DbgMsg( "%p -> unhandled event type %d received",
411 p_vout, xevent.type );
416 /* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
417 * are handled - according to the man pages, the format is always 32
419 while( XCheckTypedEvent( p_vout->p_sys->p_display,
420 ClientMessage, &xevent ) )
422 if( (xevent.xclient.message_type == p_vout->p_sys->wm_protocols)
423 && (xevent.xclient.data.l[0] == p_vout->p_sys->wm_delete_window ) )
425 p_main->p_intf->b_die = 1;
429 intf_DbgMsg( "%p -> unhandled ClientMessage received", p_vout );
433 if( (p_vout->i_width != p_vout->p_sys->i_width) ||
434 (p_vout->i_height != p_vout->p_sys->i_height) )
436 /* If video output size has changed, change interface window size */
437 intf_DbgMsg( "resizing output window" );
438 p_vout->p_sys->i_width = p_vout->i_width;
439 p_vout->p_sys->i_height = p_vout->i_height;
440 XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window,
441 p_vout->p_sys->i_width, p_vout->p_sys->i_height );
444 if( (p_vout->i_changes & VOUT_GRAYSCALE_CHANGE))
446 /* FIXME: clear flags ?? */
452 if( p_vout->i_changes & VOUT_SIZE_CHANGE )
454 intf_DbgMsg( "vout: resizing window" );
455 p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
458 XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->window,
459 p_vout->i_width, p_vout->i_height );
461 /* Destroy XImages to change their size */
464 /* Recreate XImages. If SysInit failed, the thread cannot go on. */
465 if( vout_Init( p_vout ) )
467 intf_ErrMsg( "vout error: cannot resize display" );
471 intf_Msg( "vout: video display resized (%dx%d)",
472 p_vout->i_width, p_vout->i_height );
479 /*****************************************************************************
480 * vout_Display: displays previously rendered output
481 *****************************************************************************
482 * This function send the currently rendered image to X11 server, wait until
483 * it is displayed and switch the two rendering buffer, preparing next frame.
484 *****************************************************************************/
485 static void vout_Display( vout_thread_t *p_vout )
487 boolean_t b_draw = 1;
488 const int i_size = p_vout->i_width * p_vout->i_height;
490 switch( p_vout->p_rendered_pic->i_type )
492 case YUV_422_PICTURE:
493 intf_ErrMsg( "vout error: YUV_422_PICTURE not (yet) supported" );
497 case YUV_444_PICTURE:
498 intf_ErrMsg( "vout error: YUV_444_PICTURE not (yet) supported" );
502 case YUV_420_PICTURE:
503 memcpy( p_vout->p_sys->p_xvimage->data,
504 p_vout->p_rendered_pic->p_y, i_size );
505 memcpy( p_vout->p_sys->p_xvimage->data + ( i_size ),
506 p_vout->p_rendered_pic->p_v, i_size / 4 );
507 memcpy( p_vout->p_sys->p_xvimage->data + ( i_size ) + ( i_size / 4 ),
508 p_vout->p_rendered_pic->p_u, i_size / 4 );
514 int i_dummy, i_src_width, i_src_height,
515 i_dest_width, i_dest_height, i_dest_x, i_dest_y;
518 /* Could use p_vout->p_sys->i_width and p_vout->p_sys->i_height
519 *instead of calling XGetGeometry? */
520 XGetGeometry( p_vout->p_sys->p_display, p_vout->p_sys->window,
521 &window, &i_dummy, &i_dummy,
522 &i_src_width, &i_src_height, &i_dummy, &i_dummy );
524 XVideoOutputCoords( p_vout->p_rendered_pic, p_vout->b_scale,
525 i_src_width, i_src_height, &i_dest_x, &i_dest_y,
526 &i_dest_width, &i_dest_height);
528 XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->xv_port,
529 p_vout->p_sys->window, p_vout->p_sys->gc,
530 p_vout->p_sys->p_xvimage,
531 0 /*src_x*/, 0 /*src_y*/,
532 p_vout->p_rendered_pic->i_width,
533 p_vout->p_rendered_pic->i_height,
534 i_dest_x, i_dest_y, i_dest_width, i_dest_height,
539 static void vout_SetPalette( p_vout_thread_t p_vout,
540 u16 *red, u16 *green, u16 *blue, u16 *transp )
545 /* following functions are local */
547 /*****************************************************************************
548 * XVideoCheckForXv: check for the XVideo extension
549 *****************************************************************************/
550 static int XVideoCheckForXv( Display *dpy )
554 switch( XvQueryExtension( dpy, &i, &i, &i, &i, &i ) )
560 intf_ErrMsg( "vout error: XvBadExtension" );
564 intf_ErrMsg( "vout error: XvBadAlloc" );
568 intf_ErrMsg( "vout error: XvQueryExtension failed" );
573 /*****************************************************************************
574 * XVideoCreateWindow: open and set-up XVideo main window
575 *****************************************************************************/
576 static int XVideoCreateWindow( vout_thread_t *p_vout )
578 XSizeHints xsize_hints;
579 XSetWindowAttributes xwindow_attributes;
583 boolean_t b_configure_notify;
584 boolean_t b_map_notify;
586 /* Set main window's size */
587 p_vout->p_sys->i_width = main_GetIntVariable( VOUT_WIDTH_VAR,
588 VOUT_WIDTH_DEFAULT );
589 p_vout->p_sys->i_height = main_GetIntVariable( VOUT_HEIGHT_VAR,
590 VOUT_HEIGHT_DEFAULT );
592 /* Prepare window manager hints and properties */
593 xsize_hints.base_width = p_vout->p_sys->i_width;
594 xsize_hints.base_height = p_vout->p_sys->i_height;
595 xsize_hints.flags = PSize;
596 p_vout->p_sys->wm_protocols = XInternAtom( p_vout->p_sys->p_display,
597 "WM_PROTOCOLS", True );
598 p_vout->p_sys->wm_delete_window = XInternAtom( p_vout->p_sys->p_display,
599 "WM_DELETE_WINDOW", True );
601 /* Prepare window attributes */
602 xwindow_attributes.backing_store = Always; /* save the hidden part */
603 xwindow_attributes.background_pixel = WhitePixel( p_vout->p_sys->p_display,
604 p_vout->p_sys->i_screen );
606 xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
608 /* Create the window and set hints - the window must receive ConfigureNotify
609 * events, and, until it is displayed, Expose and MapNotify events. */
610 p_vout->p_sys->window =
611 XCreateWindow( p_vout->p_sys->p_display,
612 DefaultRootWindow( p_vout->p_sys->p_display ),
614 p_vout->p_sys->i_width, p_vout->p_sys->i_height, 1,
616 CWBackingStore | CWBackPixel | CWEventMask,
617 &xwindow_attributes );
619 /* Set window manager hints and properties: size hints, command,
620 * window's name, and accepted protocols */
621 XSetWMNormalHints( p_vout->p_sys->p_display, p_vout->p_sys->window,
623 XSetCommand( p_vout->p_sys->p_display, p_vout->p_sys->window,
624 p_main->ppsz_argv, p_main->i_argc );
625 XStoreName( p_vout->p_sys->p_display, p_vout->p_sys->window,
626 VOUT_TITLE " (XVideo output)" );
628 if( (p_vout->p_sys->wm_protocols == None) /* use WM_DELETE_WINDOW */
629 || (p_vout->p_sys->wm_delete_window == None)
630 || !XSetWMProtocols( p_vout->p_sys->p_display, p_vout->p_sys->window,
631 &p_vout->p_sys->wm_delete_window, 1 ) )
633 /* WM_DELETE_WINDOW is not supported by window manager */
634 intf_Msg( "vout error: missing or bad window manager" );
637 /* Creation of a graphic context that doesn't generate a GraphicsExpose
638 * event when using functions like XCopyArea */
639 xgcvalues.graphics_exposures = False;
640 p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display,
641 p_vout->p_sys->window,
642 GCGraphicsExposures, &xgcvalues);
644 /* Send orders to server, and wait until window is displayed - three
645 * events must be received: a MapNotify event, an Expose event allowing
646 * drawing in the window, and a ConfigureNotify to get the window
647 * dimensions. Once those events have been received, only ConfigureNotify
648 * events need to be received. */
650 b_configure_notify = 0;
652 XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
655 XNextEvent( p_vout->p_sys->p_display, &xevent);
656 if( (xevent.type == Expose)
657 && (xevent.xexpose.window == p_vout->p_sys->window) )
661 else if( (xevent.type == MapNotify)
662 && (xevent.xmap.window == p_vout->p_sys->window) )
666 else if( (xevent.type == ConfigureNotify)
667 && (xevent.xconfigure.window == p_vout->p_sys->window) )
669 b_configure_notify = 1;
670 p_vout->p_sys->i_width = xevent.xconfigure.width;
671 p_vout->p_sys->i_height = xevent.xconfigure.height;
673 } while( !( b_expose && b_configure_notify && b_map_notify ) );
675 XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
676 StructureNotifyMask | KeyPressMask |
677 ButtonPressMask | ButtonReleaseMask );
679 /* At this stage, the window is open, displayed, and ready to
684 /*****************************************************************************
685 * XVideoCreateShmImage: create an XImage using shared memory extension
686 *****************************************************************************
687 * Prepare an XImage for DisplayX11ShmImage function.
688 * The order of the operations respects the recommandations of the mit-shm
689 * document by J.Corbet and K.Packard. Most of the parameters were copied from
691 *****************************************************************************/
692 static int XVideoCreateShmImage( vout_thread_t *p_vout, XvImage **pp_xvimage,
693 XShmSegmentInfo *p_shm_info)
696 XvAdaptorInfo *adaptor_info;
698 /* find xv_port... */
699 switch( XvQueryAdaptors( p_vout->p_sys->p_display,
700 DefaultRootWindow( p_vout->p_sys->p_display ),
701 &i_adaptors, &adaptor_info ) )
707 intf_ErrMsg( "vout error: XvBadExtension for XvQueryAdaptors" );
711 intf_ErrMsg( "vout error: XvBadAlloc for XvQueryAdaptors" );
715 intf_ErrMsg( "vout error: XvQueryAdaptors failed" );
719 /* XXX is this right? */
720 p_vout->p_sys->xv_port = adaptor_info[ i_adaptors - 1 ].base_id;
722 #define GUID_YUV12_PLANAR 0x32315659
724 *pp_xvimage = XvShmCreateImage( p_vout->p_sys->p_display,
725 p_vout->p_sys->xv_port,
726 GUID_YUV12_PLANAR, 0,
727 p_vout->i_width, p_vout->i_height,
730 p_shm_info->shmid = shmget( IPC_PRIVATE, (*pp_xvimage)->data_size,
732 p_shm_info->shmaddr = (*pp_xvimage)->data = shmat( p_shm_info->shmid,
734 p_shm_info->readOnly = False;
736 shmctl( p_shm_info->shmid, IPC_RMID, 0 ); /* XXX */
738 if( !XShmAttach(p_vout->p_sys->p_display, p_shm_info) )
740 intf_ErrMsg( "vout error: XShmAttach failed" );
744 /* Send image to X server. This instruction is required, since having
745 * built a Shm XImage and not using it causes an error on XCloseDisplay */
746 XFlush( p_vout->p_sys->p_display );
751 /*****************************************************************************
752 * XVideoDestroyShmImage
753 *****************************************************************************
754 * Destroy XImage AND associated data. Detach shared memory segment from
755 * server and process, then free it. If pointer is NULL, the image won't be
756 * destroyed (see vout_ManageOutputMethod())
757 *****************************************************************************/
758 static void XVideoDestroyShmImage( vout_thread_t *p_vout, XvImage *p_xvimage,
759 XShmSegmentInfo *p_shm_info )
761 /* If pointer is NULL, do nothing */
762 if( p_xvimage == NULL )
767 XShmDetach( p_vout->p_sys->p_display, p_shm_info );/* detach from server */
769 XDestroyImage( p_ximage );
771 /* XvDestroyImage( p_xvimage ); XXX */
774 if( shmdt( p_shm_info->shmaddr ) ) /* detach shared memory from process */
775 { /* also automatic freeing... */
776 intf_ErrMsg( "vout error: cannot detach shared memory (%s)",
781 /*****************************************************************************
782 * XVideoEnableScreenSaver: enable screen saver
783 *****************************************************************************
784 * This function enable the screen saver on a display after it had been
785 * disabled by XDisableScreenSaver. Both functions use a counter mechanism to
786 * know wether the screen saver can be activated or not: if n successive calls
787 * are made to XDisableScreenSaver, n successive calls to XEnableScreenSaver
788 * will be required before the screen saver could effectively be activated.
789 *****************************************************************************/
790 void XVideoEnableScreenSaver( vout_thread_t *p_vout )
792 intf_DbgMsg( "intf: enabling screen saver" );
793 XSetScreenSaver( p_vout->p_sys->p_display, p_vout->p_sys->i_ss_timeout,
794 p_vout->p_sys->i_ss_interval,
795 p_vout->p_sys->i_ss_blanking,
796 p_vout->p_sys->i_ss_exposure );
799 /*****************************************************************************
800 * XVideoDisableScreenSaver: disable screen saver
801 *****************************************************************************
802 * See XEnableScreenSaver
803 *****************************************************************************/
804 void XVideoDisableScreenSaver( vout_thread_t *p_vout )
806 /* Save screen saver informations */
807 XGetScreenSaver( p_vout->p_sys->p_display, &p_vout->p_sys->i_ss_timeout,
808 &p_vout->p_sys->i_ss_interval,
809 &p_vout->p_sys->i_ss_blanking,
810 &p_vout->p_sys->i_ss_exposure );
812 /* Disable screen saver */
813 intf_DbgMsg( "intf: disabling screen saver" );
814 XSetScreenSaver( p_vout->p_sys->p_display, 0,
815 p_vout->p_sys->i_ss_interval,
816 p_vout->p_sys->i_ss_blanking,
817 p_vout->p_sys->i_ss_exposure );
820 /*****************************************************************************
821 * XVideoTogglePointer: hide or show the mouse pointer
822 *****************************************************************************
823 * This function hides the X pointer if it is visible by putting it at
824 * coordinates (32,32) and setting the pointer sprite to a blank one. To
825 * show it again, we disable the sprite and restore the original coordinates.
826 *****************************************************************************/
827 void XVideoTogglePointer( vout_thread_t *p_vout )
829 static Cursor cursor;
830 static boolean_t b_cursor = 0;
832 if( p_vout->p_sys->b_mouse )
834 p_vout->p_sys->b_mouse = 0;
839 Pixmap blank = XCreatePixmap( p_vout->p_sys->p_display,
840 DefaultRootWindow(p_vout->p_sys->p_display),
843 XParseColor( p_vout->p_sys->p_display,
844 XCreateColormap( p_vout->p_sys->p_display,
846 p_vout->p_sys->p_display ),
848 p_vout->p_sys->p_display,
849 p_vout->p_sys->i_screen ),
853 cursor = XCreatePixmapCursor( p_vout->p_sys->p_display,
854 blank, blank, &color, &color, 1, 1 );
858 XDefineCursor( p_vout->p_sys->p_display,
859 p_vout->p_sys->window, cursor );
863 p_vout->p_sys->b_mouse = 1;
865 XUndefineCursor( p_vout->p_sys->p_display, p_vout->p_sys->window );
869 /* This based on some code in SetBufferPicture... At the moment it's only
870 * used by the xvideo plugin, but others may want to use it. */
871 static void XVideoOutputCoords( const picture_t *p_pic, const boolean_t scale,
872 const int win_w, const int win_h,
873 int *dx, int *dy, int *w, int *h)
877 *w = p_pic->i_width; *h = p_pic->i_height;
882 switch( p_pic->i_aspect_ratio )
884 case AR_3_4_PICTURE: *h = win_w * 3 / 4; break;
885 case AR_16_9_PICTURE: *h = win_w * 9 / 16; break;
886 case AR_221_1_PICTURE: *h = win_w * 100 / 221; break;
887 case AR_SQUARE_PICTURE:
888 default: *h = win_w; break;
894 switch( p_pic->i_aspect_ratio )
896 case AR_3_4_PICTURE: *w = win_h * 4 / 3; break;
897 case AR_16_9_PICTURE: *w = win_h * 16 / 9; break;
898 case AR_221_1_PICTURE: *w = win_h * 221 / 100; break;
899 case AR_SQUARE_PICTURE:
900 default: *w = win_h; break;
905 /* Set picture position */
906 *dx = (win_w - *w) / 2;
907 *dy = (win_h - *h) / 2;