x11.c 3.94 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
/*****************************************************************************
 * x11.c: Screen capture module.
 *****************************************************************************
 * Copyright (C) 2004 VideoLAN
 * $Id$
 *
 * Authors: Gildas Bazin <gbazin@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>

#include <vlc/vlc.h>
#include <vlc/input.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>

#include "screen.h"

int screen_InitCapture( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    Display *p_display;
    XWindowAttributes win_info;
    int i_chroma;

    /* Open the display */
    p_display = XOpenDisplay( NULL );
    if( !p_display )
    {
        msg_Err( p_demux, "cannot open display" );
        return VLC_EGENERIC;
    }
    p_sys->p_data = (void *)p_display;

    /* Get the parameters of the root window */
    if( !XGetWindowAttributes( p_display,
                               DefaultRootWindow( p_display ),
                               &win_info ) )
    {
        msg_Err( p_demux, "can't get root window attributes" );
        XCloseDisplay( p_display );
        return VLC_EGENERIC;
    }

    switch( win_info.depth )
    {
    case 8: /* FIXME: set the palette */
        i_chroma = VLC_FOURCC('R','G','B','2'); break;
    case 15:
        i_chroma = VLC_FOURCC('R','V','1','5'); break;
    case 16:
        i_chroma = VLC_FOURCC('R','V','1','6'); break;
    case 24:
    case 32:
gbazin's avatar
gbazin committed
73 74 75
        i_chroma = VLC_FOURCC('R','V','3','2');
        win_info.depth = 32;
        break;
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
    default:
        msg_Err( p_demux, "unknown screen depth %i", win_info.depth );
        XCloseDisplay( p_display );
        return VLC_EGENERIC;
    }

    es_format_Init( &p_sys->fmt, VIDEO_ES, i_chroma );
    p_sys->fmt.video.i_width  = win_info.width;
    p_sys->fmt.video.i_height = win_info.height;
    p_sys->fmt.video.i_bits_per_pixel = win_info.depth;

#if 0
    win_info.visual->red_mask;
    win_info.visual->green_mask;
    win_info.visual->blue_mask;
    win_info.visual->bits_per_rgb;
#endif

    return VLC_SUCCESS;
}

int screen_CloseCapture( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    Display *p_display = (Display *)p_sys->p_data;

    XCloseDisplay( p_display );
    return VLC_SUCCESS;
}

block_t *screen_Capture( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    Display *p_display = (Display *)p_sys->p_data;
    block_t *p_block;
    XImage *image;
    int i_size;

    image = XGetImage( p_display, DefaultRootWindow( p_display ),
                       0, 0, p_sys->fmt.video.i_width,
                       p_sys->fmt.video.i_height, AllPlanes, ZPixmap );

    if( !image )
    {
        msg_Warn( p_demux, "cannot get image" );
        return 0;
    }

    i_size = image->bytes_per_line * image->height;

    if( !( p_block = block_New( p_demux, i_size ) ) )
    {
        msg_Warn( p_demux, "cannot get block" );
        XDestroyImage( image );
        return 0;
    }

    memcpy( p_block->p_buffer, image->data, i_size );

    XDestroyImage( image );

    return p_block;
}