Commit 06614416 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

wl_shell_surface: basic Wayland shell surface window provider

parent 6eafc08b
......@@ -3215,6 +3215,24 @@ AS_IF([test "${have_vdpau}" = "yes" -a "${have_avcodec}" = "yes"], [
AM_CONDITIONAL([HAVE_AVCODEC_VDPAU], [test "${have_avcodec_vdpau}" = "yes"])
dnl
dnl Wayland
dnl
AC_ARG_ENABLE(wayland,
[AS_HELP_STRING([--enable-wayland], [Wayland support (default auto)])])
have_wayland="no"
AS_IF([test "${enable_wayland}" != "no"], [
PKG_CHECK_MODULES([WAYLAND_CLIENT], [wayland-client >= 1.4], [
have_wayland="yes"
], [
AS_IF([test -n "${enable_wayland}"], [
AC_MSG_ERROR([${WAYLAND_CLIENT_PKG_ERRORS}.])
])
])
])
AM_CONDITIONAL([HAVE_WAYLAND], [test "${have_wayland}" = "yes"])
dnl
dnl SDL module
dnl
......
......@@ -419,6 +419,7 @@ $Id$
* windrive: Windows logical disc drives
* wingdi: WIN 32 / WIN CE GDI video output
* winstore: Windows Store App audio output
* wl_shell_surface: Wayland shell surface window provider
* wma_fixed: wma decoder using integer decoder from Rockbox
* x262: MPEG-2 video encoder using x262
* x26410b: H264 10 bit video encoder using x264
......
......@@ -128,6 +128,15 @@ endif
endif
### Wayland ###
libwl_shell_surface_plugin_la_SOURCES = wl/shell_surface.c
libwl_shell_surface_plugin_la_CFLAGS = $(WAYLAND_CLIENT_CFLAGS)
libwl_shell_surface_plugin_la_LIBADD = $(WAYLAND_CLIENT_LIBS)
if HAVE_WAYLAND
vout_LTLIBRARIES += libwl_shell_surface_plugin.la
endif
### Win32 ###
libdirect2d_plugin_la_SOURCES = msw/direct2d.c \
msw/common.c msw/common.h msw/events.c msw/events.h \
......
/**
* @file shell_surface.c
* @brief Wayland shell surface provider module for VLC media player
*/
/*****************************************************************************
* Copyright © 2014 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 <assert.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <poll.h>
#include <wayland-client.h>
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_vout_window.h>
struct vout_window_sys_t
{
struct wl_compositor *compositor;
struct wl_output *output;
struct wl_shell *shell;
struct wl_shell_surface *shell_surface;
vlc_thread_t thread;
};
/** Background thread for Wayland shell events handling */
static void *Thread(void *data)
{
vout_window_t *wnd = data;
struct wl_display *display = wnd->display.wl;
struct pollfd ufd[1];
int canc = vlc_savecancel();
ufd[0].fd = wl_display_get_fd(display);
ufd[0].events = POLLIN;
for (;;)
{
while (wl_display_prepare_read(display) != 0)
wl_display_dispatch_pending(display);
wl_display_flush(display);
vlc_restorecancel(canc);
while (poll(ufd, 1, -1) < 0);
canc = vlc_savecancel();
wl_display_read_events(display);
wl_display_dispatch_pending(display);
}
assert(0);
//vlc_restorecancel(canc);
//return NULL;
}
static int Control(vout_window_t *wnd, int cmd, va_list ap)
{
vout_window_sys_t *sys = wnd->sys;
struct wl_display *display = wnd->display.wl;
switch (cmd)
{
case VOUT_WINDOW_SET_STATE:
return VLC_EGENERIC;
case VOUT_WINDOW_SET_SIZE:
assert(0);
break;
case VOUT_WINDOW_SET_FULLSCREEN:
{
bool fs = va_arg(ap, int);
if (fs && sys->output != NULL)
wl_shell_surface_set_fullscreen(sys->shell_surface, 1, 0,
sys->output);
else
wl_shell_surface_set_toplevel(sys->shell_surface);
break;
}
default:
msg_Err(wnd, "request %d not implemented", cmd);
return VLC_EGENERIC;
}
wl_display_flush(display);
return VLC_SUCCESS;
}
static void shell_surface_ping_cb(void *data,
struct wl_shell_surface *shell_surface,
uint32_t serial)
{
(void) data;
wl_shell_surface_pong(shell_surface, serial);
}
static void shell_surface_configure_cb(void *data,
struct wl_shell_surface *shell_surface,
uint32_t edges,
int32_t width, int32_t height)
{
vout_window_t *wnd = data;
msg_Err(wnd, "FIXME resize to %"PRId32"x%"PRId32, width, height);
(void) shell_surface;
(void) edges;
}
static void shell_surface_popup_done_cb(void *data,
struct wl_shell_surface *shell_surface)
{
(void) data; (void) shell_surface;
}
static const struct wl_shell_surface_listener shell_surface_cbs =
{
shell_surface_ping_cb,
shell_surface_configure_cb,
shell_surface_popup_done_cb,
};
static void registry_global_cb(void *data, struct wl_registry *registry,
uint32_t name, const char *iface, uint32_t vers)
{
vout_window_t *wnd = data;
vout_window_sys_t *sys = wnd->sys;
msg_Dbg(wnd, "global %3"PRIu32": %s version %"PRIu32, name, iface, vers);
if (!strcmp(iface, "wl_compositor"))
sys->compositor = wl_registry_bind(registry, name,
&wl_compositor_interface, 1);
else
if (!strcmp(iface, "wl_output"))
sys->output = wl_registry_bind(registry, name, &wl_output_interface,
1);
else
if (!strcmp(iface, "wl_shell"))
sys->shell = wl_registry_bind(registry, name, &wl_shell_interface, 1);
}
static void registry_global_remove_cb(void *data, struct wl_registry *registry,
uint32_t name)
{
vout_window_t *wnd = data;
msg_Dbg(wnd, "global remove %3"PRIu32, name);
(void) registry;
}
static const struct wl_registry_listener registry_cbs =
{
registry_global_cb,
registry_global_remove_cb,
};
/**
* Creates a Wayland shell surface.
*/
static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg)
{
vout_window_sys_t *sys = malloc(sizeof (*sys));
if (unlikely(sys == NULL))
return VLC_ENOMEM;
sys->compositor = NULL;
sys->output = NULL;
sys->shell = NULL;
sys->shell_surface = NULL;
wnd->sys = sys;
/* Connect to the display server */
char *dpy_name = var_InheritString(wnd, "wl-display");
struct wl_display *display = wl_display_connect(dpy_name);
free(dpy_name);
if (display == NULL)
{
free(sys);
return VLC_EGENERIC;
}
/* Find the interesting singleton(s) */
struct wl_registry *registry = wl_display_get_registry(display);
if (registry == NULL)
goto error;
wl_registry_add_listener(registry, &registry_cbs, wnd);
wl_display_roundtrip(display);
wl_registry_destroy(registry);
if (sys->compositor == NULL || sys->shell == NULL)
goto error;
/* Create a surface */
struct wl_surface *surface = wl_compositor_create_surface(sys->compositor);
if (surface == NULL)
goto error;
struct wl_shell_surface *shell_surface =
wl_shell_get_shell_surface(sys->shell, surface);
if (shell_surface == NULL)
goto error;
sys->shell_surface = shell_surface;
wl_shell_surface_add_listener(shell_surface, &shell_surface_cbs, wnd);
wl_shell_surface_set_class(shell_surface, PACKAGE_NAME);
wl_shell_surface_set_toplevel(shell_surface);
char *title = var_InheritString(wnd, "video-title");
wl_shell_surface_set_title(shell_surface, title ? title
: _("VLC media player"));
free(title);
//if (var_InheritBool (wnd, "keyboard-events"))
// do_something();
if (vlc_clone (&sys->thread, Thread, wnd, VLC_THREAD_PRIORITY_LOW))
goto error;
wl_display_flush(display);
wnd->handle.wl = surface;
wnd->display.wl = display;
wnd->control = Control;
(void) cfg;
return VLC_SUCCESS;
error:
if (sys->shell_surface != NULL)
wl_shell_surface_destroy(sys->shell_surface);
if (sys->shell != NULL)
wl_shell_destroy(sys->shell);
if (sys->output != NULL)
wl_output_destroy(sys->output);
if (sys->compositor != NULL)
wl_compositor_destroy(sys->compositor);
wl_display_disconnect(display);
free(sys);
return VLC_EGENERIC;
}
/**
* Destroys a Wayland shell surface.
*/
static void Close(vout_window_t *wnd)
{
vout_window_sys_t *sys = wnd->sys;
vlc_cancel(sys->thread);
vlc_join(sys->thread, NULL);
wl_shell_surface_destroy(sys->shell_surface);
wl_surface_destroy(wnd->handle.wl);
wl_shell_destroy(sys->shell);
wl_output_destroy(sys->output);
wl_compositor_destroy(sys->compositor);
wl_display_disconnect(wnd->display.wl);
free(sys);
}
#define DISPLAY_TEXT N_("Wayland display")
#define DISPLAY_LONGTEXT N_( \
"Video will be rendered with this Wayland display. " \
"If empty, the default display will be used.")
vlc_module_begin ()
set_shortname (N_("WL shell"))
set_description (N_("Wayland shell surface"))
set_category (CAT_VIDEO)
set_subcategory (SUBCAT_VIDEO_VOUT)
set_capability ("vout surface wl", 10)
set_callbacks (Open, Close)
add_string ("wl-display", NULL, DISPLAY_TEXT, DISPLAY_LONGTEXT, true)
vlc_module_end ()
......@@ -1176,6 +1176,7 @@ modules/video_output/msw/wingdi.c
modules/video_output/sdl.c
modules/video_output/vdummy.c
modules/video_output/vmem.c
modules/video_output/wl/shell_surface.c
modules/video_output/xcb/glx.c
modules/video_output/xcb/window.c
modules/video_output/xcb/x11.c
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment