libxcb_plugin_la_SOURCES = \
xcb/xcb_vlc.h \
xcb/x11.c \
+ xcb/common.c \
xcb/events.c
libxcb_plugin_la_CFLAGS = $(AM_CFLAGS) \
$(XCB_CFLAGS) $(XCB_SHM_CFLAGS) \
--- /dev/null
+/**
+ * @file common.c
+ * @brief Common code for XCB video output plugins
+ */
+/*****************************************************************************
+ * Copyright © 2009 Rémi Denis-Courmont
+ *
+ * This library 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.0
+ * of the License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ ****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include <sys/types.h>
+#include <sys/shm.h>
+
+#include <xcb/xcb.h>
+#include <xcb/shm.h>
+
+#include <vlc_common.h>
+#include <vlc_vout.h>
+#include <vlc_window.h>
+
+#include "xcb_vlc.h"
+
+/**
+ * Connect to the X server.
+ */
+xcb_connection_t *Connect (vlc_object_t *obj)
+{
+ char *display = var_CreateGetNonEmptyString (obj, "x11-display");
+ xcb_connection_t *conn = xcb_connect (display, NULL);
+
+ free (display);
+ if (xcb_connection_has_error (conn) /*== NULL*/)
+ {
+ msg_Err (obj, "cannot connect to X server");
+ xcb_disconnect (conn);
+ return NULL;
+ }
+ return conn;
+}
+
+
+/**
+ * Create a VLC video X window object, find the corresponding X server screen,
+ * and probe the MIT-SHM extension.
+ */
+vout_window_t *GetWindow (vout_thread_t *obj,
+ xcb_connection_t *conn,
+ const xcb_screen_t **restrict pscreen,
+ bool *restrict pshm)
+{
+ /* Get window */
+ xcb_window_t root;
+ vout_window_t *wnd = vout_RequestXWindow (obj, &(int){ 0 }, &(int){ 0 },
+ &(unsigned){ 0 }, &(unsigned){ 0 });
+ if (wnd == NULL)
+ {
+ msg_Err (obj, "parent window not available");
+ return NULL;
+ }
+ else
+ {
+ xcb_get_geometry_reply_t *geo;
+ xcb_get_geometry_cookie_t ck;
+
+ ck = xcb_get_geometry (conn, wnd->handle.xid);
+ geo = xcb_get_geometry_reply (conn, ck, NULL);
+ if (geo == NULL)
+ {
+ msg_Err (obj, "parent window not valid");
+ goto error;
+ }
+ root = geo->root;
+ free (geo);
+
+ /* Subscribe to parent window resize events */
+ const uint32_t value = XCB_EVENT_MASK_STRUCTURE_NOTIFY;
+ xcb_change_window_attributes (conn, wnd->handle.xid,
+ XCB_CW_EVENT_MASK, &value);
+ }
+
+ /* Find the selected screen */
+ const xcb_setup_t *setup = xcb_get_setup (conn);
+ xcb_screen_t *screen = NULL;
+ for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup);
+ i.rem > 0 && screen == NULL; xcb_screen_next (&i))
+ {
+ if (i.data->root == root)
+ screen = i.data;
+ }
+
+ if (screen == NULL)
+ {
+ msg_Err (obj, "parent window screen not found");
+ goto error;
+ }
+ msg_Dbg (obj, "using screen 0x%"PRIx32, root);
+
+ /* Check MIT-SHM shared memory support */
+ bool shm = var_CreateGetBool (obj, "x11-shm") > 0;
+ if (shm)
+ {
+ xcb_shm_query_version_cookie_t ck;
+ xcb_shm_query_version_reply_t *r;
+
+ ck = xcb_shm_query_version (conn);
+ r = xcb_shm_query_version_reply (conn, ck, NULL);
+ if (!r)
+ {
+ msg_Err (obj, "shared memory (MIT-SHM) not available");
+ msg_Warn (obj, "display will be slow");
+ shm = false;
+ }
+ free (r);
+ }
+
+ *pscreen = screen;
+ *pshm = shm;
+ return wnd;
+
+error:
+ vout_ReleaseWindow (wnd);
+ return NULL;
+}
+
+/**
+ * Gets the size of an X window.
+ */
+int GetWindowSize (struct vout_window_t *wnd, xcb_connection_t *conn,
+ unsigned *restrict width, unsigned *restrict height)
+{
+ xcb_get_geometry_cookie_t ck = xcb_get_geometry (conn, wnd->handle.xid);
+ xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, ck, NULL);
+
+ if (!geo)
+ return -1;
+
+ *width = geo->width;
+ *height = geo->height;
+ free (geo);
+ return 0;
+}
return VLC_ENOMEM;
vout->p_sys = p_sys;
- p_sys->conn = NULL;
- p_sys->embed = NULL;
/* Connect to X */
- char *display = var_CreateGetNonEmptyString (vout, "x11-display");
- p_sys->conn = xcb_connect (display, NULL);
- if (xcb_connection_has_error (p_sys->conn) /*== NULL*/)
- {
- msg_Err (vout, "cannot connect to X server %s",
- display ? display : "");
- free (display);
- goto error;
- }
- free (display);
+ p_sys->conn = Connect (obj);
+ if (p_sys->conn == NULL)
+ return VLC_EGENERIC;
/* Get window */
- p_sys->embed = vout_RequestXWindow (vout, &(int){ 0 }, &(int){ 0 },
- &(unsigned){ 0 }, &(unsigned){ 0 });
+ const xcb_screen_t *scr;
+ p_sys->embed = GetWindow (vout, p_sys->conn, &scr, &p_sys->shm);
if (p_sys->embed == NULL)
{
- msg_Err (vout, "parent window not available");
- goto error;
- }
- xcb_window_t root;
- {
- xcb_get_geometry_reply_t *geo;
- xcb_get_geometry_cookie_t ck;
-
- ck = xcb_get_geometry (p_sys->conn, p_sys->embed->handle.xid);
- geo = xcb_get_geometry_reply (p_sys->conn, ck, NULL);
- if (geo == NULL)
- {
- msg_Err (vout, "parent window not valid");
- goto error;
- }
- root = geo->root;
- free (geo);
-
- /* Subscribe to parent window resize events */
- const uint32_t value = XCB_EVENT_MASK_STRUCTURE_NOTIFY;
- xcb_change_window_attributes (p_sys->conn, p_sys->embed->handle.xid,
- XCB_CW_EVENT_MASK, &value);
+ xcb_disconnect (p_sys->conn);
+ return VLC_EGENERIC;
}
- /* Find the selected screen */
const xcb_setup_t *setup = xcb_get_setup (p_sys->conn);
p_sys->byte_order = setup->image_byte_order;
- xcb_screen_t *scr = NULL;
- for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup);
- i.rem > 0 && scr == NULL; xcb_screen_next (&i))
- {
- if (i.data->root == root)
- scr = i.data;
- }
-
- if (scr == NULL)
- {
- msg_Err (vout, "parent window screen not found");
- goto error;
- }
- msg_Dbg (vout, "using screen 0x%"PRIx32, scr->root);
-
/* Determine our video format. Normally, this is done in pf_init(), but
* this plugin always uses the same format for a given X11 screen. */
xcb_visualid_t vid = 0;
/* Byte sex is a non-issue for 8-bits. It can be worked around with
* RGB masks for 24-bits. Too bad for 15-bits and 16-bits. */
-#ifdef WORDS_BIGENDIAN
-# define ORDER XCB_IMAGE_ORDER_MSB_FIRST
-#else
-# define ORDER XCB_IMAGE_ORDER_LSB_FIRST
-#endif
if (fmt->bits_per_pixel == 16 && setup->image_byte_order != ORDER)
continue;
xcb_create_gc (p_sys->conn, p_sys->gc, p_sys->window, 0, NULL);
msg_Dbg (vout, "using X11 graphic context %08"PRIx32, p_sys->gc);
- /* Check shared memory support */
- p_sys->shm = var_CreateGetBool (vout, "x11-shm") > 0;
- if (p_sys->shm)
- {
- xcb_shm_query_version_cookie_t ck;
- xcb_shm_query_version_reply_t *r;
-
- ck = xcb_shm_query_version (p_sys->conn);
- r = xcb_shm_query_version_reply (p_sys->conn, ck, NULL);
- if (!r)
- {
- msg_Err (vout, "shared memory (MIT-SHM) not available");
- msg_Warn (vout, "display will be slow");
- p_sys->shm = false;
- }
- free (r);
- }
-
vout->pf_init = Init;
vout->pf_end = Deinit;
vout->pf_display = Display;
vout_thread_t *vout = (vout_thread_t *)obj;
vout_sys_t *p_sys = vout->p_sys;
- if (p_sys->embed)
- vout_ReleaseWindow (p_sys->embed);
+ vout_ReleaseWindow (p_sys->embed);
/* colormap and window are garbage-collected by X */
- if (p_sys->conn)
- xcb_disconnect (p_sys->conn);
+ xcb_disconnect (p_sys->conn);
free (p_sys);
}
shmdt (pic->p->p_pixels);
}
-static void get_window_size (xcb_connection_t *conn, xcb_window_t win,
- unsigned *width, unsigned *height)
-{
- xcb_get_geometry_cookie_t ck = xcb_get_geometry (conn, win);
- xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, ck, NULL);
-
- if (geo)
- {
- *width = geo->width;
- *height = geo->height;
- free (geo);
- }
- else
- *width = *height = 0;
-}
-
/**
* Allocate drawable window and picture buffers.
*/
vout_sys_t *p_sys = vout->p_sys;
unsigned x, y, width, height;
- get_window_size (p_sys->conn, p_sys->embed->handle.xid, &width, &height);
+ if (GetWindowSize (p_sys->embed, p_sys->conn, &width, &height))
+ return VLC_EGENERIC;
vout_PlacePicture (vout, width, height, &x, &y, &width, &height);
const uint32_t values[] = { x, y, width, height, };
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
+#ifdef WORDS_BIGENDIAN
+# define ORDER XCB_IMAGE_ORDER_MSB_FIRST
+#else
+# define ORDER XCB_IMAGE_ORDER_LSB_FIRST
+#endif
+
int CheckError (vout_thread_t *, const char *str, xcb_void_cookie_t);
int ProcessEvent (vout_thread_t *, xcb_connection_t *, xcb_window_t,
xcb_generic_event_t *);
key_handler_t *CreateKeyHandler (vlc_object_t *, xcb_connection_t *);
void DestroyKeyHandler (key_handler_t *);
int ProcessKeyEvent (key_handler_t *, xcb_generic_event_t *);
+
+/* common.c */
+struct vout_window_t;
+
+xcb_connection_t *Connect (vlc_object_t *obj);
+struct vout_window_t *GetWindow (vout_thread_t *obj,
+ xcb_connection_t *pconn,
+ const xcb_screen_t **restrict pscreen,
+ bool *restrict pshm);
+int GetWindowSize (struct vout_window_t *wnd, xcb_connection_t *conn,
+ unsigned *restrict width, unsigned *restrict height);