[vlc-commits] xdg-shell: move output handling to separate file

Rémi Denis-Courmont git at videolan.org
Thu May 24 19:33:13 CEST 2018


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Thu May 24 19:10:56 2018 +0300| [21047ec421f4bdfb1345284ebe285965b7aee237] | committer: Rémi Denis-Courmont

xdg-shell: move output handling to separate file

This follows the model already used for seats (i.e. inputs).
This avoids one race-prone round-trip at start-up.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=21047ec421f4bdfb1345284ebe285965b7aee237
---

 modules/video_output/Makefile.am         |   1 +
 modules/video_output/wayland/output.c    | 162 +++++++++++++++++++++++++++++++
 modules/video_output/wayland/output.h    |  28 ++++++
 modules/video_output/wayland/xdg-shell.c |  96 ++----------------
 4 files changed, 201 insertions(+), 86 deletions(-)

diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
index 279f461efd..89b71a4dc6 100644
--- a/modules/video_output/Makefile.am
+++ b/modules/video_output/Makefile.am
@@ -212,6 +212,7 @@ libwl_shell_plugin_la_CFLAGS = $(libxdg_shell_plugin_la_CFLAGS)
 libwl_shell_plugin_la_LIBADD = $(libxdg_shell_plugin_la_LIBADD)
 
 libxdg_shell_plugin_la_SOURCES = \
+	video_output/wayland/output.h video_output/wayland/output.c \
 	video_output/wayland/input.h video_output/wayland/input.c \
 	video_output/xcb/vlc_xkb.h video_output/xcb/xkb.c \
 	video_output/wayland/xdg-shell.c
diff --git a/modules/video_output/wayland/output.c b/modules/video_output/wayland/output.c
new file mode 100644
index 0000000000..dc85aac7c7
--- /dev/null
+++ b/modules/video_output/wayland/output.c
@@ -0,0 +1,162 @@
+/**
+ * @file input.c
+ * @brief Wayland input events for VLC media player
+ */
+/*****************************************************************************
+ * Copyright © 2018 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <wayland-client.h>
+#include <vlc_common.h>
+#include <vlc_vout_window.h>
+
+#include "output.h"
+
+/* TODO: xdg_output protocol */
+
+struct output_data
+{
+    vout_window_t *owner;
+    struct wl_output *wl_output;
+
+    uint32_t name;
+    struct wl_list node;
+};
+
+static void output_geometry_cb(void *data, struct wl_output *output,
+                               int32_t x, int32_t y, int32_t w, int32_t h,
+                               int32_t sp, const char *make, const char *model,
+                               int32_t transform)
+{
+    struct output_data *od = data;
+    vout_window_t *wnd = od->owner;
+    char idstr[11];
+    char *name;
+
+    msg_Dbg(wnd, "output %"PRIu32" geometry: %"PRId32"x%"PRId32"mm"
+            "+%"PRId32"+%"PRId32", subpixel %"PRId32", transform %"PRId32,
+            od->name, w, h, x, y, sp, transform);
+
+    sprintf(idstr, "%"PRIu32, od->name);
+    if (likely(asprintf(&name, "%s - %s", make, model) >= 0))
+    {
+        vout_window_ReportOutputDevice(wnd, idstr, name);
+        free(name);
+    }
+    (void) output;
+}
+
+static void output_mode_cb(void *data, struct wl_output *output,
+                           uint32_t flags, int32_t w, int32_t h, int32_t vr)
+{
+    struct output_data *od = data;
+    vout_window_t *wnd = od->owner;
+    div_t d = div(vr, 1000);
+
+    msg_Dbg(wnd, "output %"PRIu32" mode: 0x%"PRIx32" %"PRId32"x%"PRId32
+            ", %d.%03d Hz", od->name, flags, w, h, d.quot, d.rem);
+    (void) output;
+}
+
+static void output_done_cb(void *data, struct wl_output *output)
+{
+    (void) data; (void) output;
+}
+
+static void output_scale_cb(void *data, struct wl_output *output, int32_t f)
+{
+    struct output_data *od = data;
+    vout_window_t *wnd = od->owner;
+
+    msg_Dbg(wnd, "output %"PRIu32" scale: %"PRId32, od->name, f);
+    (void) output;
+}
+
+static const struct wl_output_listener wl_output_cbs =
+{
+    output_geometry_cb,
+    output_mode_cb,
+    output_done_cb,
+    output_scale_cb,
+};
+
+int output_create(vout_window_t *wnd, struct wl_registry *registry,
+                  uint32_t name, uint32_t version, struct wl_list *list)
+{
+    struct output_data *od = malloc(sizeof (*od));
+    if (unlikely(od == NULL))
+        return -1;
+
+    if (version > 2)
+        version = 2;
+
+    od->wl_output = wl_registry_bind(registry, name, &wl_output_interface,
+                                     version);
+    if (unlikely(od->wl_output == NULL))
+    {
+        free(od);
+        return -1;
+    }
+
+    od->owner = wnd;
+    od->name = name;
+
+    wl_output_add_listener(od->wl_output, &wl_output_cbs, od);
+    wl_list_insert(list, &od->node);
+    return 0;
+}
+
+static void output_destroy(struct output_data *od)
+{
+    char idstr[11];
+
+    sprintf(idstr, "%"PRIu32, od->name);
+    vout_window_ReportOutputDevice(od->owner, idstr, NULL);
+
+    wl_list_remove(&od->node);
+    wl_output_destroy(od->wl_output);
+    free(od);
+}
+
+int output_destroy_one(struct wl_list *list, uint32_t name)
+{
+    struct output_data *od;
+
+    wl_list_for_each(od, list, node)
+    {
+        if (od->name == name)
+        {
+            output_destroy(od);
+            /* Note: return here so no needs for safe walk variant */
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+void output_destroy_all(struct wl_list *list)
+{
+    while (!wl_list_empty(list))
+        output_destroy(container_of(list->next, struct output_data, node));
+}
diff --git a/modules/video_output/wayland/output.h b/modules/video_output/wayland/output.h
new file mode 100644
index 0000000000..7d6710d90e
--- /dev/null
+++ b/modules/video_output/wayland/output.h
@@ -0,0 +1,28 @@
+/*****************************************************************************
+ * Copyright © 2018 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include <stdint.h>
+
+struct vout_window_t;
+struct wl_registry;
+struct wl_list;
+
+int output_create(struct vout_window_t *wnd, struct wl_registry *,
+                  uint32_t name, uint32_t version, struct wl_list *list);
+int output_destroy_one(struct wl_list *list, uint32_t name);
+void output_destroy_all(struct wl_list *list);
diff --git a/modules/video_output/wayland/xdg-shell.c b/modules/video_output/wayland/xdg-shell.c
index 40dca03738..06d3a286a5 100644
--- a/modules/video_output/wayland/xdg-shell.c
+++ b/modules/video_output/wayland/xdg-shell.c
@@ -65,6 +65,7 @@
 #include <vlc_vout_window.h>
 
 #include "input.h"
+#include "output.h"
 
 struct vout_window_sys_t
 {
@@ -85,6 +86,7 @@ struct vout_window_sys_t
     bool unstable;
 #endif
 
+    struct wl_list outputs;
     struct wl_list seats;
 
     vlc_thread_t thread;
@@ -130,12 +132,6 @@ static void *Thread(void *data)
     //return NULL;
 }
 
-struct device_data
-{
-    uint32_t name;
-    struct vout_window_t *window;
-};
-
 static int Control(vout_window_t *wnd, int cmd, va_list ap)
 {
     vout_window_sys_t *sys = wnd->sys;
@@ -321,64 +317,6 @@ static const struct wl_shell_surface_listener wl_shell_surface_cbs =
 #define xdg_surface_cbs wl_shell_surface_cbs
 #endif
 
-static void output_geometry_cb(void *data, struct wl_output *output,
-                               int32_t x, int32_t y, int32_t w, int32_t h,
-                               int32_t sp, const char *make, const char *model,
-                               int32_t transform)
-{
-    struct device_data *dd = data;
-    struct vout_window_t *wnd = dd->window;
-    char idstr[11];
-    char *name;
-
-    msg_Dbg(wnd, "output %"PRIu32" geometry: %"PRId32"x%"PRId32"mm"
-            "+%"PRId32"+%"PRId32", subpixel %"PRId32", transform %"PRId32,
-            dd->name, w, h, x, y, sp, transform);
-
-    sprintf(idstr, "%"PRIu32, dd->name);
-    if (likely(asprintf(&name, "%s - %s", make, model) >= 0))
-    {
-        vout_window_ReportOutputDevice(wnd, idstr, name);
-        free(name);
-    }
-    (void) output;
-}
-
-static void output_mode_cb(void *data, struct wl_output *output,
-                           uint32_t flags, int32_t w, int32_t h, int32_t vr)
-{
-    struct device_data *dd = data;
-    struct vout_window_t *wnd = dd->window;
-    div_t d = div(vr, 1000);
-
-    msg_Dbg(wnd, "output %"PRIu32" mode: 0x%"PRIx32" %"PRId32"x%"PRId32
-            ", %d.%03d Hz", dd->name, flags, w, h, d.quot, d.rem);
-    (void) output;
-}
-
-static void output_done_cb(void *data, struct wl_output *output)
-{
-    wl_output_destroy(output);
-    free(data);
-}
-
-static void output_scale_cb(void *data, struct wl_output *output, int32_t f)
-{
-    struct device_data *dd = data;
-    struct vout_window_t *wnd = dd->window;
-
-    msg_Dbg(wnd, "output %"PRIu32" scale: %"PRId32, dd->name, f);
-    (void) output;
-}
-
-static const struct wl_output_listener output_cbs =
-{
-    output_geometry_cb,
-    output_mode_cb,
-    output_done_cb,
-    output_scale_cb,
-};
-
 static void registry_global_cb(void *data, struct wl_registry *registry,
                                uint32_t name, const char *iface, uint32_t vers)
 {
@@ -392,22 +330,6 @@ static void registry_global_cb(void *data, struct wl_registry *registry,
                                            &wl_compositor_interface,
                                            (vers < 2) ? vers : 2);
     else
-    if (!strcmp(iface, "wl_output") && vers >= 2)
-    {
-        struct device_data *dd = malloc(sizeof (*dd));
-        if (unlikely(dd == NULL))
-            return;
-
-        struct wl_output *output = wl_registry_bind(registry, name,
-                                                    &wl_output_interface, 2);
-        if (unlikely(output == NULL))
-            return;
-
-        dd->name = name;
-        dd->window = wnd;
-        wl_output_add_listener(output, &output_cbs, dd);
-    }
-    else
 #ifdef XDG_SHELL
 # ifdef XDG_SHELL_UNSTABLE
     if (!strcmp(iface, "zxdg_shell_v6") && sys->wm_base == NULL)
@@ -436,6 +358,9 @@ static void registry_global_cb(void *data, struct wl_registry *registry,
     if (!strcmp(iface, "wl_seat"))
         seat_create(wnd, registry, name, vers, &sys->seats);
     else
+    if (!strcmp(iface, "wl_output"))
+        output_create(wnd, registry, name, vers, &sys->outputs);
+    else
     if (!strcmp(iface, "org_kde_kwin_server_decoration_manager"))
         sys->deco_manager = wl_registry_bind(registry, name,
                          &org_kde_kwin_server_decoration_manager_interface, 1);
@@ -446,16 +371,13 @@ static void registry_global_remove_cb(void *data, struct wl_registry *registry,
 {
     vout_window_t *wnd = data;
     vout_window_sys_t *sys = wnd->sys;
-    char idstr[11];
 
     msg_Dbg(wnd, "global remove %3"PRIu32, name);
 
     if (seat_destroy_one(&sys->seats, name) == 0)
         return;
-
-    /* If the global was an output, this will remove it. Otherwise, no-op. */
-    sprintf(idstr, "%"PRIu32, name);
-    vout_window_ReportOutputDevice(wnd, idstr, NULL);
+    if (output_destroy_one(&sys->outputs, name) == 0)
+        return;
 
     (void) registry;
 }
@@ -485,6 +407,7 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg)
     sys->width = cfg->width;
     sys->height = cfg->height;
     sys->fullscreen = false;
+    wl_list_init(&sys->outputs);
     wl_list_init(&sys->seats);
     wnd->sys = sys;
     wnd->handle.wl = NULL;
@@ -511,7 +434,6 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg)
 #endif
     wl_registry_add_listener(sys->registry, &registry_cbs, wnd);
     wl_display_roundtrip(display); /* complete registry enumeration */
-    wl_display_roundtrip(display); /* complete devices enumeration */
 
     if (sys->compositor == NULL || sys->wm_base == NULL)
         goto error;
@@ -601,6 +523,7 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg)
 
 error:
     seat_destroy_all(&sys->seats);
+    output_destroy_all(&sys->outputs);
     if (sys->deco != NULL)
         org_kde_kwin_server_decoration_destroy(sys->deco);
     if (sys->deco_manager != NULL)
@@ -633,6 +556,7 @@ static void Close(vout_window_t *wnd)
     vlc_join(sys->thread, NULL);
 
     seat_destroy_all(&sys->seats);
+    output_destroy_all(&sys->outputs);
     if (sys->deco != NULL)
         org_kde_kwin_server_decoration_destroy(sys->deco);
     if (sys->deco_manager != NULL)



More information about the vlc-commits mailing list