2cd3bedcfe3bae478b7f97d2a37f07df6bea4981
[vlc.git] / modules / access / screen / x11.c
1 /*****************************************************************************
2  * x11.c: Screen capture module.
3  *****************************************************************************
4  * Copyright (C) 2004-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *          Antoine Cellerier <dionoea at videolan dot org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <vlc_common.h>
34
35 #include <X11/Xlib.h>
36 #include <X11/Xutil.h>
37
38 #include "screen.h"
39
40 int screen_InitCapture( demux_t *p_demux )
41 {
42     demux_sys_t *p_sys = p_demux->p_sys;
43     Display *p_display;
44     XWindowAttributes win_info;
45     int i_chroma;
46
47     /* Open the display */
48     p_display = XOpenDisplay( NULL );
49     if( !p_display )
50     {
51         msg_Err( p_demux, "cannot open display" );
52         return VLC_EGENERIC;
53     }
54     p_sys->p_data = (void *)p_display;
55
56     /* Get the parameters of the root window */
57     if( !XGetWindowAttributes( p_display,
58                                DefaultRootWindow( p_display ),
59                                &win_info ) )
60     {
61         msg_Err( p_demux, "can't get root window attributes" );
62         XCloseDisplay( p_display );
63         return VLC_EGENERIC;
64     }
65
66     switch( win_info.depth )
67     {
68     case 8: /* FIXME: set the palette */
69         i_chroma = VLC_FOURCC('R','G','B','2'); break;
70     case 15:
71         i_chroma = VLC_FOURCC('R','V','1','5'); break;
72     case 16:
73         i_chroma = VLC_FOURCC('R','V','1','6'); break;
74     case 24:
75     case 32:
76         i_chroma = VLC_FOURCC('R','V','3','2');
77         win_info.depth = 32;
78         break;
79     default:
80         msg_Err( p_demux, "unknown screen depth %i", win_info.depth );
81         XCloseDisplay( p_display );
82         return VLC_EGENERIC;
83     }
84
85     es_format_Init( &p_sys->fmt, VIDEO_ES, i_chroma );
86     p_sys->fmt.video.i_visible_width =
87     p_sys->fmt.video.i_width  = win_info.width;
88     p_sys->fmt.video.i_visible_height =
89     p_sys->fmt.video.i_height = win_info.height;
90     p_sys->fmt.video.i_bits_per_pixel = win_info.depth;
91     p_sys->fmt.video.i_chroma = i_chroma;
92
93 #if 0
94     win_info.visual->red_mask;
95     win_info.visual->green_mask;
96     win_info.visual->blue_mask;
97     win_info.visual->bits_per_rgb;
98 #endif
99
100     return VLC_SUCCESS;
101 }
102
103 int screen_CloseCapture( demux_t *p_demux )
104 {
105     demux_sys_t *p_sys = p_demux->p_sys;
106     Display *p_display = (Display *)p_sys->p_data;
107
108     XCloseDisplay( p_display );
109     if( p_sys->p_blend )
110     {
111         module_unneed( p_sys->p_blend, p_sys->p_blend->p_module );
112         vlc_object_detach( p_sys->p_blend );
113         vlc_object_release( p_sys->p_blend );
114     }
115     return VLC_SUCCESS;
116 }
117
118 block_t *screen_Capture( demux_t *p_demux )
119 {
120     demux_sys_t *p_sys = p_demux->p_sys;
121     Display *p_display = (Display *)p_sys->p_data;
122     block_t *p_block;
123     XImage *image;
124     int i_size;
125     int root_x = 0, root_y = 0;
126
127     if( p_sys->b_follow_mouse || p_sys->p_mouse )
128     {
129         Window root = DefaultRootWindow( p_display ), child;
130         int win_x, win_y;
131         unsigned int mask;
132         if( XQueryPointer( p_display, root,
133             &root, &child, &root_x, &root_y, &win_x, &win_y,
134             &mask ) )
135         {
136             if( p_sys->b_follow_mouse )
137                 FollowMouse( p_sys, root_x, root_y );
138         }
139         else
140             msg_Dbg( p_demux, "XQueryPointer() failed" );
141
142     }
143
144     image = XGetImage( p_display, DefaultRootWindow( p_display ),
145                        p_sys->i_left, p_sys->i_top, p_sys->fmt.video.i_width,
146                        p_sys->fmt.video.i_height, AllPlanes, ZPixmap );
147
148     if( !image )
149     {
150         msg_Warn( p_demux, "cannot get image" );
151         return 0;
152     }
153
154     i_size = image->bytes_per_line * image->height;
155
156     if( !( p_block = block_New( p_demux, i_size ) ) )
157     {
158         msg_Warn( p_demux, "cannot get block" );
159         XDestroyImage( image );
160         return 0;
161     }
162
163     vlc_memcpy( p_block->p_buffer, image->data, i_size );
164
165     if( p_sys->p_mouse )
166         RenderCursor( p_demux, root_x, root_y,
167                       p_block->p_buffer );
168
169     XDestroyImage( image );
170
171     return p_block;
172 }
173