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