XCB: factor some code
authorRémi Denis-Courmont <remi@remlab.net>
Sun, 19 Apr 2009 09:20:49 +0000 (12:20 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Sat, 25 Apr 2009 19:10:35 +0000 (22:10 +0300)
modules/video_output/Modules.am
modules/video_output/xcb/common.c [new file with mode: 0644]
modules/video_output/xcb/x11.c
modules/video_output/xcb/xcb_vlc.h

index f318b63..f427735 100644 (file)
@@ -23,6 +23,7 @@ SOURCES_yuv = yuv.c
 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) \
diff --git a/modules/video_output/xcb/common.c b/modules/video_output/xcb/common.c
new file mode 100644 (file)
index 0000000..afc0133
--- /dev/null
@@ -0,0 +1,160 @@
+/**
+ * @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;
+}
index 86b11c9..d6e8eec 100644 (file)
@@ -113,69 +113,24 @@ static int Open (vlc_object_t *obj)
         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;
@@ -224,11 +179,6 @@ static int Open (vlc_object_t *obj)
 
         /* 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;
 
@@ -323,24 +273,6 @@ static int Open (vlc_object_t *obj)
     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;
@@ -361,11 +293,9 @@ static void Close (vlc_object_t *obj)
     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);
 }
 
@@ -438,22 +368,6 @@ static void PictureDeinit (vout_thread_t *vout, picture_t *pic)
     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.
  */
@@ -462,7 +376,8 @@ static int Init (vout_thread_t *vout)
     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, };
index efedd02..d6c4b88 100644 (file)
  * 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 *);
@@ -28,3 +34,14 @@ typedef struct key_handler_t key_handler_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);