[packages/plymouth] - added git patch to update the package to current state - removed Fedora junk - removed duplicate s

baggins baggins at pld-linux.org
Tue Apr 29 19:50:23 CEST 2014


commit 612b1f7781e3faa0950b6e9d8cdf6be7d009849b
Author: Jan Rękorajski <baggins at pld-linux.org>
Date:   Tue Apr 29 19:39:57 2014 +0200

    - added git patch to update the package to current state
    - removed Fedora junk
    - removed duplicate services provided upstream
    - static libs no longer provided by upstream
    - updated patches
    - rel 9

 charge.plymouth                       |    13 -
 path-udevadm.patch                    |    11 -
 plymouth-git.patch                    | 11238 ++++++++++++++++++++++++++++++++
 plymouth.spec                         |   121 +-
 systemd-ask-password-plymouth.path    |    20 -
 systemd-ask-password-plymouth.service |    19 -
 text-colors.patch                     |    19 +-
 7 files changed, 11294 insertions(+), 147 deletions(-)
---
diff --git a/plymouth.spec b/plymouth.spec
index 3297aeb..894f4f4 100644
--- a/plymouth.spec
+++ b/plymouth.spec
@@ -1,20 +1,15 @@
 # TODO
 # - integrate with geninitrd
 # - pldize recent update (r1.18)
-# - verify if systemd services have to be installed for targets,
-#	and remove the symlinks if not
 #
 # Conditional build:
-%bcond_without	drm_intel	# disable building with libdrm_intel support
-%bcond_without	drm_radeon	# disable building with libdrm_radeon support
-%bcond_with	drm_nouveau	# enable building with libdrm_nouveau support
-%bcond_without	kms		# disable building with libkms support
+%bcond_without	drm		# disable building with DRM renderer support
 
 Summary:	Graphical Boot Animation and Logger
 Summary(pl.UTF-8):	Graficzna animacja i logowanie startu systemu
 Name:		plymouth
 Version:	0.8.8
-Release:	8
+Release:	9
 License:	GPL v2+
 Group:		Base
 Source0:	http://www.freedesktop.org/software/plymouth/releases/%{name}-%{version}.tar.bz2
@@ -22,25 +17,20 @@ Source0:	http://www.freedesktop.org/software/plymouth/releases/%{name}-%{version
 Source1:	%{name}-logo.png
 # Source1-md5:	6b38a868585adfd3a96a4ad16973c1f8
 Source2:	%{name}.tmpfiles
-Source3:	charge.%{name}
 Source4:	boot-duration
-Source5:	%{name}-set-default-plugin
 Source6:	%{name}-update-initrd
-Source7:	systemd-ask-password-plymouth.path
-Source8:	systemd-ask-password-plymouth.service
 Patch0:		text-colors.patch
-Patch1:		path-udevadm.patch
-Patch2:		%{name}-restore-suspend.patch
+Patch1:		%{name}-restore-suspend.patch
+Patch100:	%{name}-git.patch
 URL:		http://www.freedesktop.org/wiki/Software/Plymouth
 BuildRequires:	cairo-devel
 BuildRequires:	gtk+2-devel >= 2:2.12.0
-%if %{with drm_intel} ||  %{with drm_radeon} ||  %{with drm_nouveau} ||  %{with kms}
-BuildRequires:	libdrm-devel
-%endif
 BuildRequires:	xorg-lib-libpciaccess-devel
+%{?with_drm:BuildRequires:	libdrm-devel}
 BuildRequires:	libpng-devel >= 2:1.2.16
 BuildRequires:	pango-devel >= 1:1.21.0
 BuildRequires:	pkgconfig
+BuildRequires:	udev-devel
 Requires:	%{name}-graphics-libs = %{version}-%{release}
 Requires(post):	%{name}-scripts = %{version}-%{release}
 Requires:	/etc/os-release
@@ -253,23 +243,22 @@ This metapackage tracks the current distribution default theme.
 %description system-theme -l pl.UTF-8
 Ten metapakiet śledzi domyślny motyw dystrybucji.
 
-%package theme-charge
-Summary:	Plymouth "Charge" theme
-Summary(pl.UTF-8):	Motyw Plymouth "Charge"
+%package theme-glow
+Summary:	Plymouth "Glow" theme
+Summary(pl.UTF-8):	Motyw Plymouth "Glow"
 Group:		Base
 Requires:	%{name}-plugin-two-step = %{version}-%{release}
 Requires(post):	%{name}-scripts = %{version}-%{release}
 Provides:	%{name}(system-theme) = %{version}-%{release}
+Obsoletes:	plymouth-theme-charge
 
-%description theme-charge
-This package contains the "charge" boot splash theme for Plymouth. It
-features the shadowy hull of a Fedora logo charge up and and finally
-burst into full form.
+%description theme-glow
+This package contains the "Glow" boot splash theme for Plymouth.
+Corporate theme with pie chart boot progress followed by a glowing
+emerging logo.
 
-%description theme-charge -l pl.UTF-8
-Ten pakiet zawiera motyw ekranu startowego Plymouth "Charge". Odznacza
-się on cieniowaną łupiną loga Fedory, która rośnie, a ostatecznie
-wybucha do pełnej postaci.
+%description theme-glow -l pl.UTF-8
+Ten pakiet zawiera motyw ekranu startowego Plymouth "Glow".
 
 %package theme-fade-in
 Summary:	Plymouth "Fade-In" theme
@@ -357,21 +346,21 @@ Odznacza się on małym kółkiem kręcącym się na ciemnym tle.
 
 %prep
 %setup -q
+%patch100 -p1
 %patch0 -p1
 %patch1 -p1
-%patch2 -p1
-
-# Change the default theme
-sed -i -e 's/fade-in/charge/g' src/plymouthd.defaults
 
 %build
+%{__aclocal}
+%{__autoconf}
+%{__autoheader}
+%{__automake}
 %configure \
-	%{__enable_disable drm_intel libdrm_intel} \
-	%{__enable_disable drm_radeon libdrm_radeon} \
-	%{__enable_disable drm_nouveau libdrm_nouveau} \
-	%{__enable_disable kms libkms} \
+	UDEVADM=/sbin/udevadm \
+	SYSTEMD_ASK_PASSWORD_AGENT=/bin/systemd-tty-ask-password-agent \
+	%{__enable_disable drm drm} \
 	--disable-silent-rules \
-	--disable-tests \
+	--enable-documentation \
 	--disable-gdm-transition \
 	--enable-systemd-integration \
 	--enable-tracing \
@@ -392,7 +381,6 @@ install -d $RPM_BUILD_ROOT{%{_bindir},%{_libdir},%{_pixmapsdir},%{systemdtmpfile
 %{__make} install \
 	DESTDIR=$RPM_BUILD_ROOT
 
-%{__mv} $RPM_BUILD_ROOT/%{_lib}/lib*.a $RPM_BUILD_ROOT%{_libdir}
 ln -sf /%{_lib}/$(basename $RPM_BUILD_ROOT/%{_lib}/libply.so.*.*.*) $RPM_BUILD_ROOT%{_libdir}/libply.so
 ln -sf /%{_lib}/$(basename $RPM_BUILD_ROOT/%{_lib}/libply-splash-core.so.*.*.*) $RPM_BUILD_ROOT%{_libdir}/libply-splash-core.so
 %{__rm} $RPM_BUILD_ROOT/%{_lib}/libply{,-splash-core}.so
@@ -401,47 +389,18 @@ install -d $RPM_BUILD_ROOT%{_localstatedir}/lib/plymouth
 cp -p %{SOURCE4} $RPM_BUILD_ROOT%{_datadir}/plymouth/default-boot-duration
 > $RPM_BUILD_ROOT%{_localstatedir}/lib/plymouth/boot-duration
 
-# FC: Add charge, our new default
-install -d $RPM_BUILD_ROOT%{_datadir}/plymouth/themes/charge
-cp %{SOURCE3} $RPM_BUILD_ROOT%{_datadir}/plymouth/themes/charge
-cp $RPM_BUILD_ROOT%{_datadir}/plymouth/themes/glow/{box,bullet,entry,lock}.png $RPM_BUILD_ROOT%{_datadir}/plymouth/themes/charge
-
-# FC: Drop glow, it's not very Fedora-y
-%{__rm} -r $RPM_BUILD_ROOT%{_datadir}/plymouth/themes/glow
-
-# FC: Override plymouth-update-initrd to work dracut or mkinitrd
+# Override plymouth-update-initrd to work with dracut or mkinitrd
 cp -p %{SOURCE6} $RPM_BUILD_ROOT%{_libdir}/plymouth/plymouth-update-initrd
 
-# FC: Add compat script for upgrades
-install -p %{SOURCE5} $RPM_BUILD_ROOT%{_sbindir}
-
 %{__rm} $RPM_BUILD_ROOT{/%{_lib},%{_libdir}}/*.la \
-	$RPM_BUILD_ROOT%{_libdir}/plymouth/*.{a,la} \
-	$RPM_BUILD_ROOT%{_libdir}/plymouth/renderers/*.{a,la}
-
-# Temporary symlink until rc.sysinit is fixed
-ln -sf /bin/plymouth $RPM_BUILD_ROOT%{_bindir}/plymouth
+	$RPM_BUILD_ROOT%{_libdir}/plymouth/*.la \
+	$RPM_BUILD_ROOT%{_libdir}/plymouth/renderers/*.la
 
 install -d $RPM_BUILD_ROOT%{_localstatedir}/lib/plymouth
 
 cp -p %{SOURCE1} $RPM_BUILD_ROOT%{_pixmapsdir}/plymouth-logo.png
 cp -p %{SOURCE2} $RPM_BUILD_ROOT%{systemdtmpfilesdir}/%{name}.conf
 
-cp -p %{SOURCE7} $RPM_BUILD_ROOT%{systemdunitdir}/systemd-ask-password-plymouth.path
-cp -p %{SOURCE8} $RPM_BUILD_ROOT%{systemdunitdir}/systemd-ask-password-plymouth.service
-
-# install plymouth services for targets
-# http://cgit.freedesktop.org/systemd/systemd/commit/?id=26cbf29c52a36b6ad9d1ccc16d8f7adccefeddca
-install -d $RPM_BUILD_ROOT%{systemdunitdir}/{halt,kexec,poweroff,reboot,sysinit,multi-user}.target.wants
-ln -sf ../plymouth-start.service $RPM_BUILD_ROOT%{systemdunitdir}/sysinit.target.wants/plymouth-start.service
-ln -sf ../plymouth-read-write.service $RPM_BUILD_ROOT%{systemdunitdir}/sysinit.target.wants/plymouth-read-write.service
-ln -sf ../plymouth-quit.service $RPM_BUILD_ROOT%{systemdunitdir}/multi-user.target.wants/plymouth-quit.service
-ln -sf ../plymouth-quit-wait.service $RPM_BUILD_ROOT%{systemdunitdir}/multi-user.target.wants/plymouth-quit-wait.service
-ln -sf ../plymouth-reboot.service $RPM_BUILD_ROOT%{systemdunitdir}/reboot.target.wants/plymouth-reboot.service
-ln -sf ../plymouth-kexec.service $RPM_BUILD_ROOT%{systemdunitdir}/kexec.target.wants/plymouth-kexec.service
-ln -sf ../plymouth-poweroff.service $RPM_BUILD_ROOT%{systemdunitdir}/poweroff.target.wants/plymouth-poweroff.service
-ln -sf ../plymouth-halt.service $RPM_BUILD_ROOT%{systemdunitdir}/halt.target.wants/plymouth-halt.service
-
 %clean
 rm -rf $RPM_BUILD_ROOT
 
@@ -462,7 +421,6 @@ fi
 %files
 %defattr(644,root,root,755)
 %doc AUTHORS README TODO
-%attr(755,root,root) %{_bindir}/plymouth
 %dir %{_sysconfdir}/plymouth
 %config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/plymouth/plymouthd.conf
 %{_mandir}/man8/plymouth.8*
@@ -470,22 +428,27 @@ fi
 %attr(755,root,root) /sbin/plymouthd
 %attr(755,root,root) %{_libdir}/plymouth/details.so
 %attr(755,root,root) %{_libdir}/plymouth/text.so
+%attr(755,root,root) %{_libdir}/plymouth/tribar.so
 %attr(755,root,root) %{_libdir}/plymouth/renderers/drm.so
 %attr(755,root,root) %{_libdir}/plymouth/renderers/frame-buffer.so
 %dir %{_datadir}/plymouth
 %dir %{_datadir}/plymouth/themes
 %dir %{_datadir}/plymouth/themes/details
 %dir %{_datadir}/plymouth/themes/text
+%dir %{_datadir}/plymouth/themes/tribar
 %{_datadir}/plymouth/plymouthd.defaults
 %{_datadir}/plymouth/default-boot-duration
 %{_datadir}/plymouth/themes/details/details.plymouth
 %{_datadir}/plymouth/themes/text/text.plymouth
+%{_datadir}/plymouth/themes/tribar/tribar.plymouth
 %{_pixmapsdir}/plymouth-logo.png
 %{systemdtmpfilesdir}/%{name}.conf
 %dir %{_localstatedir}/lib/plymouth
 %ghost %{_localstatedir}/lib/plymouth/boot-duration
 %{_localstatedir}/run/plymouth
 %{_localstatedir}/spool/plymouth
+%{_mandir}/man1/plymouth.1*
+%{_mandir}/man8/plymouthd.8*
 
 %{systemdunitdir}/plymouth-halt.service
 %{systemdunitdir}/plymouth-kexec.service
@@ -501,6 +464,7 @@ fi
 %{systemdunitdir}/halt.target.wants/plymouth-halt.service
 %dir %{systemdunitdir}/initrd-switch-root.target.wants
 %{systemdunitdir}/initrd-switch-root.target.wants/plymouth-switch-root.service
+%{systemdunitdir}/initrd-switch-root.target.wants/plymouth-start.service
 %{systemdunitdir}/kexec.target.wants/plymouth-kexec.service
 %{systemdunitdir}/multi-user.target.wants/plymouth-quit.service
 %{systemdunitdir}/multi-user.target.wants/plymouth-quit-wait.service
@@ -537,20 +501,13 @@ fi
 %{_pkgconfigdir}/ply-splash-core.pc
 %{_pkgconfigdir}/ply-splash-graphics.pc
 
-%files static
-%defattr(644,root,root,755)
-%attr(755,root,root) %{_libdir}/libply.a
-%attr(755,root,root) %{_libdir}/libply-boot-client.a
-%attr(755,root,root) %{_libdir}/libply-splash-core.a
-%attr(755,root,root) %{_libdir}/libply-splash-graphics.a
-
 %files scripts
 %defattr(644,root,root,755)
-%attr(755,root,root) %{_sbindir}/plymouth-set-default-plugin
 %attr(755,root,root) %{_sbindir}/plymouth-set-default-theme
 %attr(755,root,root) %{_libdir}/plymouth/plymouth-generate-initrd
 %attr(755,root,root) %{_libdir}/plymouth/plymouth-populate-initrd
 %attr(755,root,root) %{_libdir}/plymouth/plymouth-update-initrd
+%{_mandir}/man1/plymouth-set-default-theme.1*
 
 %files plugin-fade-throbber
 %defattr(644,root,root,755)
@@ -579,11 +536,11 @@ fi
 %files system-theme
 %defattr(644,root,root,755)
 
-%files theme-charge
+%files theme-glow
 %defattr(644,root,root,755)
-%dir %{_datadir}/plymouth/themes/charge
-%{_datadir}/plymouth/themes/charge/*.png
-%{_datadir}/plymouth/themes/charge/charge.plymouth
+%dir %{_datadir}/plymouth/themes/glow
+%{_datadir}/plymouth/themes/glow/*.png
+%{_datadir}/plymouth/themes/glow/glow.plymouth
 
 %files theme-fade-in
 %defattr(644,root,root,755)
diff --git a/charge.plymouth b/charge.plymouth
deleted file mode 100644
index f499c0f..0000000
--- a/charge.plymouth
+++ /dev/null
@@ -1,13 +0,0 @@
-[Plymouth Theme]
-Name=Charge
-Description=A theme that features the shadowy hull of a Fedora logo charge up and and finally burst into into full form.
-ModuleName=two-step
-
-[two-step]
-ImageDir=/usr/share/plymouth/themes/charge
-HorizontalAlignment=.5
-VerticalAlignment=.5
-Transition=none
-TransitionDuration=0.0
-BackgroundStartColor=0x202020
-BackgroundEndColor=0x202020
diff --git a/path-udevadm.patch b/path-udevadm.patch
deleted file mode 100644
index 42970b6..0000000
--- a/path-udevadm.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- plymouth-0.8.8/systemd-units/plymouth-start.service.in.orig	2012-10-31 20:43:34.695979769 +0100
-+++ plymouth-0.8.8/systemd-units/plymouth-start.service.in	2012-10-31 20:44:47.219310059 +0100
-@@ -8,7 +8,7 @@
- 
- [Service]
- ExecStart=@PLYMOUTH_DAEMON_DIR@/plymouthd --mode=boot --pid-file=@plymouthruntimedir@/pid --attach-to-session
--ExecStartPost=-/bin/udevadm settle --timeout=30 --exit-if-exists=/sys/class/drm/card0/dev ; /bin/udevadm settle --timeout=30 --exit-if-exists=/sys/class/graphics/fb0/dev ; @PLYMOUTH_CLIENT_DIR@/plymouth show-splash
-+ExecStartPost=-/sbin/udevadm settle --timeout=30 --exit-if-exists=/sys/class/drm/card0/dev ; /sbin/udevadm settle --timeout=30 --exit-if-exists=/sys/class/graphics/fb0/dev ; @PLYMOUTH_CLIENT_DIR@/plymouth show-splash
- Type=forking
- KillMode=none
- SendSIGKILL=no
diff --git a/plymouth-git.patch b/plymouth-git.patch
new file mode 100644
index 0000000..a5c8b3c
--- /dev/null
+++ b/plymouth-git.patch
@@ -0,0 +1,11238 @@
+diff --git a/Makefile.am b/Makefile.am
+index b322463..395c91b 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -1,4 +1,8 @@
+-SUBDIRS = src themes images scripts docs systemd-units
++SUBDIRS = src themes images scripts systemd-units
++
++if BUILD_DOCUMENTATION
++SUBDIRS += docs
++endif
+ 
+ DISTCHECK_CONFIGURE_FLAGS = --disable-tests --without-system-root-install
+ 
+diff --git a/configure.ac b/configure.ac
+index 2ab0893..9c8f863 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -6,7 +6,7 @@ AC_CONFIG_AUX_DIR(build-tools)
+ AC_USE_SYSTEM_EXTENSIONS
+ AC_SYS_LARGEFILE
+ AC_PROG_AWK
+-AC_PROG_CC
++AC_PROG_CC_STDC
+ AM_PROG_CC_C_O
+ AC_HEADER_STDC
+ AC_C_CONST
+@@ -16,7 +16,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+ AM_MAINTAINER_MODE([enable])
+ 
+ PKG_PROG_PKG_CONFIG
+-LT_INIT
++LT_INIT([dlopen disable-static pic-only])
+ 
+ ## increment if the interface has additions, changes, removals.
+ LT_CURRENT=3
+@@ -38,12 +38,19 @@ PKG_CHECK_MODULES(IMAGE, [libpng >= 1.2.16 ])
+ AC_SUBST(IMAGE_CFLAGS)
+ AC_SUBST(IMAGE_LIBS)
+ 
++PKG_CHECK_MODULES(UDEV, [libudev]);
++AC_SUBST(UDEV_CFLAGS)
++AC_SUBST(UDEV_LIBS)
++
+ PLYMOUTH_CFLAGS=""
+ PLYMOUTH_LIBS="-lm -lrt -ldl"
+ 
+ AC_SUBST(PLYMOUTH_CFLAGS)
+ AC_SUBST(PLYMOUTH_LIBS)
+ 
++AC_PATH_PROG([SYSTEMD_ASK_PASSWORD_AGENT], [systemd-tty-ask-password-agent])
++AC_PATH_PROG([UDEVADM], [udevadm])
++
+ AC_ARG_ENABLE(pango, AS_HELP_STRING([--enable-pango],[enable building with pango, disabled there is no encryption prompts]),enable_pango=$enableval,enable_pango=yes)
+ AM_CONDITIONAL(ENABLE_PANGO,  [test "$enable_pango" = yes])
+ 
+@@ -62,148 +69,6 @@ if test x$enable_gtk = xyes; then
+   AC_SUBST(GTK_LIBS)
+ fi
+ 
+-AC_ARG_ENABLE(libdrm_intel, AS_HELP_STRING([--enable-libdrm_intel],[enable building with libdrm_intel support]),enable_libdrm_intel=$enableval,enable_libdrm_intel=no)
+-AM_CONDITIONAL(ENABLE_LIBDRM_INTEL,  [test "$enable_libdrm_intel" = yes])
+-
+-if test x$enable_libdrm_intel = xyes; then
+-  PKG_CHECK_MODULES(DRM_INTEL, [libdrm libdrm_intel])
+-  OLD_CFLAGS="$CFLAGS"
+-  CFLAGS="$CFLAGS $DRM_INTEL_CFLAGS"
+-  AC_MSG_CHECKING([if i915_drm.h is in include path])
+-  AC_COMPILE_IFELSE(AC_LANG_PROGRAM(
+-  [[
+-    #include <stdint.h>
+-    #include <stdlib.h>
+-    #include "i915_drm.h"
+-  ]],[[]]),[found_drm_intel_kernel_headers=yes],[found_drm_intel_kernel_headers=no])
+-
+-  if test "$found_drm_intel_kernel_headers" = "yes"; then
+-    AC_MSG_RESULT([yes])
+-  else
+-    AC_MSG_RESULT([no])
+-    AC_MSG_CHECKING([if we can find them anyway])
+-
+-    MORE_DRM_CFLAGS="-I`$PKG_CONFIG --variable includedir libdrm`/drm"
+-    CFLAGS="$CFLAGS $MORE_DRM_CFLAGS"
+-    AC_COMPILE_IFELSE(AC_LANG_PROGRAM(
+-    [[
+-      #include <stdint.h>
+-      #include <stdlib.h>
+-      #include "i915_drm.h"
+-    ]],[[]]),[found_drm_intel_kernel_headers=yes],[found_drm_intel_kernel_headers=no])
+-
+-    if test "$found_drm_intel_kernel_headers" = "yes"; then
+-      AC_MSG_RESULT([yes])
+-      DRM_INTEL_CFLAGS="$DRM_INTEL_CFLAGS $MORE_DRM_CFLAGS"
+-    else
+-      AC_MSG_RESULT([no])
+-      AC_MSG_ERROR([Could not find i915_drm.h])
+-    fi
+-  fi
+-
+-  AC_SUBST(DRM_INTEL_CFLAGS)
+-  AC_SUBST(DRM_INTEL_LIBS)
+-  AC_DEFINE(PLY_ENABLE_LIBDRM_INTEL, 1, [Enable support for libdrm_intel driver])
+-fi
+-
+-AC_ARG_ENABLE(libdrm_radeon, AS_HELP_STRING([--enable-libdrm_radeon],[enable building with libdrm_radeon support]),enable_libdrm_radeon=$enableval,enable_libdrm_radeon=no)
+-AM_CONDITIONAL(ENABLE_LIBDRM_RADEON,  [test "$enable_libdrm_radeon" = yes])
+-
+-if test x$enable_libdrm_radeon = xyes; then
+-  PKG_CHECK_MODULES(DRM_RADEON, [libdrm libdrm_radeon])
+-  OLD_CFLAGS="$CFLAGS"
+-  CFLAGS="$CFLAGS $DRM_RADEON_CFLAGS"
+-  AC_MSG_CHECKING([if radeon_drm.h is in include path])
+-  AC_COMPILE_IFELSE(AC_LANG_PROGRAM(
+-  [[
+-    #include <stdint.h>
+-    #include <stdlib.h>
+-    #include "radeon_drm.h"
+-  ]],[[]]),[found_drm_radeon_kernel_headers=yes],[found_drm_radeon_kernel_headers=no])
+-
+-  if test "$found_drm_radeon_kernel_headers" = "yes"; then
+-    AC_MSG_RESULT([yes])
+-  else
+-    AC_MSG_RESULT([no])
+-    AC_MSG_CHECKING([if we can find them anyway])
+-
+-    MORE_DRM_CFLAGS="-I`$PKG_CONFIG --variable includedir libdrm`/drm"
+-    CFLAGS="$CFLAGS $MORE_DRM_RADEON_CFLAGS"
+-    AC_COMPILE_IFELSE(AC_LANG_PROGRAM(
+-    [[
+-      #include <stdint.h>
+-      #include <stdlib.h>
+-      #include "radeon_drm.h"
+-    ]],[[]]),[found_drm_radeon_kernel_headers=yes],[found_drm_radeon_kernel_headers=no])
+-
+-    if test "$found_drm_radeon_kernel_headers" = "yes"; then
+-      AC_MSG_RESULT([yes])
+-      DRM_RADEON_CFLAGS="$DRM_RADEON_CFLAGS $MORE_DRM_CFLAGS"
+-    else
+-      AC_MSG_RESULT([no])
+-      AC_MSG_ERROR([Could not find radeon_drm.h])
+-    fi
+-  fi
+-
+-  AC_SUBST(DRM_RADEON_CFLAGS)
+-  AC_SUBST(DRM_RADEON_LIBS)
+-  AC_DEFINE(PLY_ENABLE_LIBDRM_RADEON, 1, [Enable support for libdrm_radeon driver])
+-fi
+-
+-AC_ARG_ENABLE(libdrm_nouveau, AS_HELP_STRING([--enable-libdrm_nouveau],[enable building with libdrm_nouveau support]),enable_libdrm_nouveau=$enableval,enable_libdrm_nouveau=no)
+-AM_CONDITIONAL(ENABLE_LIBDRM_NOUVEAU,  [test "$enable_libdrm_nouveau" = yes])
+-
+-if test x$enable_libdrm_nouveau = xyes; then
+-  PKG_CHECK_MODULES(DRM_NOUVEAU, [libdrm libdrm_nouveau])
+-  OLD_CFLAGS="$CFLAGS"
+-  CFLAGS="$CFLAGS $DRM_NOUVEAU_CFLAGS"
+-  AC_MSG_CHECKING([if nouveau_drm.h is in include path])
+-  AC_COMPILE_IFELSE(AC_LANG_PROGRAM(
+-  [[
+-    #include <stdint.h>
+-    #include <stdlib.h>
+-    #include "nouveau_drm.h"
+-  ]],[[]]),[found_drm_nouveau_kernel_headers=yes],[found_drm_nouveau_kernel_headers=no])
+-
+-  if test "$found_drm_nouveau_kernel_headers" = "yes"; then
+-    AC_MSG_RESULT([yes])
+-  else
+-    AC_MSG_RESULT([no])
+-    AC_MSG_CHECKING([if we can find them anyway])
+-
+-    MORE_DRM_CFLAGS="-I`$PKG_CONFIG --variable includedir libdrm`/drm"
+-    CFLAGS="$CFLAGS $MORE_DRM_CFLAGS"
+-    AC_COMPILE_IFELSE(AC_LANG_PROGRAM(
+-    [[
+-      #include <stdint.h>
+-      #include <stdlib.h>
+-      #include "nouveau_drm.h"
+-    ]],[[]]),[found_drm_nouveau_kernel_headers=yes],[found_drm_nouveau_kernel_headers=no])
+-
+-    if test "$found_drm_nouveau_kernel_headers" = "yes"; then
+-      AC_MSG_RESULT([yes])
+-      DRM_NOUVEAU_CFLAGS="$DRM_NOUVEAU_CFLAGS $MORE_DRM_CFLAGS"
+-    else
+-      AC_MSG_RESULT([no])
+-      AC_MSG_ERROR([Could not find nouveau_drm.h])
+-    fi
+-  fi
+-
+-  AC_SUBST(DRM_NOUVEAU_CFLAGS)
+-  AC_SUBST(DRM_NOUVEAU_LIBS)
+-  AC_DEFINE(PLY_ENABLE_LIBDRM_NOUVEAU, 1, [Enable support for libdrm_nouveau driver])
+-fi
+-
+-AC_ARG_ENABLE(libkms, AS_HELP_STRING([--enable-libkms],[enable building with libkms support]),enable_libkms=$enableval,enable_libkms=no)
+-AM_CONDITIONAL(ENABLE_LIBKMS,  [test "$enable_libkms" = yes])
+-
+-if test x$enable_libkms = xyes; then
+-  PKG_CHECK_MODULES(LIBKMS, [libdrm libkms])
+-  AC_SUBST(LIBKMS_CFLAGS)
+-  AC_SUBST(LIBKMS_LIBS)
+-  AC_DEFINE(PLY_ENABLE_LIBKMS, 1, [Enable support for libkms abstraction over drm drivers])
+-fi
+-
+ AC_ARG_ENABLE(drm, AS_HELP_STRING([--enable-drm-renderer],[enable building drm kms support]),enable_drm_renderer=$enableval,enable_drm_renderer=yes)
+ AM_CONDITIONAL(ENABLE_DRM_RENDERER,  [test "$enable_drm_renderer" = yes])
+ 
+@@ -211,10 +76,17 @@ if test x$enable_drm_renderer = xyes; then
+   PKG_CHECK_MODULES(DRM, [libdrm])
+ fi
+ 
+-DRM_CFLAGS="$DRM_CFLAGS $DRM_INTEL_CFLAGS $DRM_RADEON_CFLAGS $DRM_NOUVEAU_CFLAGS $LIBKMS_CFLAG"
+-DRM_LIBS="$DRM_LIBS $DRM_INTEL_LIBS $DRM_RADEON_LIBS $DRM_NOUVEAU_LIBS $LIBKMS_LIBS"
+-AC_SUBST(DRM_CFLAGS)
+-AC_SUBST(DRM_LIBS)
++AC_ARG_ENABLE(documentation,
++              AS_HELP_STRING([--enable-documentation],
++                             [build documentation]),,
++              enable_documentation=yes)
++if test x$enable_documentation = xyes; then
++   AC_PATH_PROG([XSLTPROC], [xsltproc])
++   if test x$XSLTPROC = x; then
++      AC_MSG_ERROR([xsltproc is required to build documentation])
++   fi
++fi
++AM_CONDITIONAL(BUILD_DOCUMENTATION, test x$enable_documentation = xyes)
+ 
+ AC_ARG_ENABLE(tracing, AS_HELP_STRING([--enable-tracing],[enable verbose tracing code]),enable_tracing=$enableval,enable_tracing=yes)
+ 
+@@ -222,10 +94,6 @@ if test x$enable_tracing = xyes; then
+   AC_DEFINE(PLY_ENABLE_TRACING, 1, [Build in verbose debug tracing spew])
+ fi
+ 
+-AC_ARG_ENABLE(tests, AS_HELP_STRING([--enable-tests],[build tests]),enable_tests=$enableval,enable_tests=yes)
+-
+-AM_CONDITIONAL(ENABLE_TESTS,  [test "$enable_tests" = yes])
+-
+ AC_ARG_ENABLE(gdm-transition, AS_HELP_STRING([--enable-gdm-transition],[enable smooth transition to gdm]),enable_gdm_transition=$enableval,enable_gdm_transition=no)
+ 
+ if test x$enable_gdm_transition = xyes; then
+@@ -254,7 +122,7 @@ AM_CONDITIONAL(ENABLE_SYSTEMD_INTEGRATION, [test "$enable_systemd_integration" =
+ 
+ if test x$enable_systemd_integration = xyes; then
+   AC_DEFINE(PLY_ENABLE_SYSTEMD_INTEGRATION, 1, [Coordinate boot up with systemd])
+-  SYSTEMD_UNIT_DIR=/lib/systemd/system
++  SYSTEMD_UNIT_DIR=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
+   AC_SUBST(SYSTEMD_UNIT_DIR)
+ fi
+ 
+@@ -278,7 +146,7 @@ AS_AC_EXPAND(PLYMOUTH_CLIENT_DIR, $plymouthclientdir)
+ AS_AC_EXPAND(PLYMOUTH_DAEMON_DIR, $plymouthdaemondir)
+ AS_AC_EXPAND(PLYMOUTH_RUNTIME_DIR, $plymouthruntimedir)
+ 
+-AC_ARG_WITH(rhgb-compat-link, AS_HELP_STRING([--with-rhgb-compat-link],[Install /usr/bin/rhgb-client compatability symlink]),with_rhgb_compat_link=${withval},with_rhgb_compat_link=yes)
++AC_ARG_WITH(rhgb-compat-link, AS_HELP_STRING([--with-rhgb-compat-link],[Install /usr/bin/rhgb-client compatability symlink]),with_rhgb_compat_link=${withval},with_rhgb_compat_link=no)
+ AM_CONDITIONAL(WITH_RHGB_COMPAT_LINK,  [test "$with_rhgb_compat_link" = yes])
+ 
+ AC_ARG_WITH(log-viewer, AS_HELP_STRING([--with-log-viewer],[Install plymouth log viewer]),with_log_viewer=${withval},with_log_viewer=no)
+@@ -328,7 +196,7 @@ AC_DEFUN([PLYMOUTH_CC_TRY_FLAG], [
+   plymouth_save_CFLAGS="$CFLAGS"
+   CFLAGS="$CFLAGS $1"
+ 
+-  AC_COMPILE_IFELSE([ ], [plymouth_cc_flag=yes], [plymouth_cc_flag=no])
++  AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ ]], [[ ]])], [plymouth_cc_flag=yes], [plymouth_cc_flag=no])
+   CFLAGS="$plymouth_save_CFLAGS"
+ 
+   if test "x$plymouth_cc_flag" = "xyes"; then
+@@ -357,7 +225,7 @@ if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
+    -Wchar-subscripts -Wmissing-declarations -Wmissing-prototypes \
+    -Wwrite-strings -Wnested-externs -Wpointer-arith \
+    -Wswitch-enum -Wstrict-aliasing=2 -Winit-self -Wunsafe-loop-optimizations \
+-   -Wno-missing-field-initializers -Wno-unused-parameter \
++   -Wno-missing-field-initializers -Wno-unused-parameter -Wno-unused-result \
+    -Wcast-align -Wsign-compare -Wp,-D_FORTIFY_SOURCE=2"
+ elif test "$GCC" = "yes"; then
+   AC_MSG_RESULT(no)
+@@ -427,6 +295,7 @@ AC_CONFIG_FILES([Makefile
+            src/plugins/splash/Makefile
+            src/plugins/splash/throbgress/Makefile
+            src/plugins/splash/fade-throbber/Makefile
++           src/plugins/splash/tribar/Makefile
+            src/plugins/splash/text/Makefile
+            src/plugins/splash/details/Makefile
+            src/plugins/splash/space-flares/Makefile
+@@ -439,12 +308,10 @@ AC_CONFIG_FILES([Makefile
+            src/client/Makefile
+            src/viewer/Makefile
+            src/upstart-bridge/Makefile
+-           src/tests/Makefile
+-           src/libply/tests/Makefile
+-           src/client/tests/Makefile
+            themes/Makefile
+            themes/spinfinity/Makefile
+            themes/fade-in/Makefile
++           themes/tribar/Makefile
+            themes/text/Makefile
+            themes/details/Makefile
+            themes/solar/Makefile
+diff --git a/docs/Makefile.am b/docs/Makefile.am
+index dedda55..1a9f7ea 100644
+--- a/docs/Makefile.am
++++ b/docs/Makefile.am
+@@ -1,4 +1,31 @@
+-dist_man_MANS = plymouth.8
++XSLTPROC_FLAGS = \
++        --nonet \
++        --stringparam man.output.quietly 1 \
++        --stringparam funcsynopsis.style ansi \
++        --stringparam man.th.extra1.suppress 1 \
++        --stringparam man.authors.section.enabled 0 \
++        --stringparam man.copyright.section.enabled 0
+ 
+-%.html: %.txt
+-	asciidoc $(ASCIIDOC_OPTS) -a toc $*.txt
++
++plymouth.1: plymouth1.xml
++	$(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
++
++%.8: %.xml
++	$(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
++	
++%.1: %.xml
++	$(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
++	
++man_MANS = \
++	plymouth.1 \
++	plymouth.8 \
++	plymouthd.8 \
++	plymouth-set-default-theme.1
++
++EXTRA_DIST = \
++	plymouth.xml \
++	plymouth1.xml \
++	plymouth-set-default-theme.xml \
++	plymouthd.xml
++
++CLEANFILES = $(man_MANS)
+diff --git a/docs/plymouth-set-default-theme.xml b/docs/plymouth-set-default-theme.xml
+new file mode 100644
+index 0000000..efb051e
+--- /dev/null
++++ b/docs/plymouth-set-default-theme.xml
+@@ -0,0 +1,103 @@
++<?xml version='1.0'?>
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
++        "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
++
++<refentry id="plymouth-set-default-theme">
++
++        <refentryinfo>
++                <title>plymouth-set-default-theme</title>
++                <productname>plymouth</productname>
++
++                <authorgroup>
++                        <author>
++                                <contrib>Developer</contrib>
++                                <firstname>Kristian</firstname>
++                                <surname>Høgsberg</surname>
++                        </author>
++                        <author>
++                                <contrib>Developer</contrib>
++                                <firstname>Ray</firstname>
++                                <surname>Strode</surname>
++                        </author>
++                </authorgroup>
++
++        </refentryinfo>
++
++        <refmeta>
++                <refentrytitle>plymouth-set-default-theme</refentrytitle>
++                <manvolnum>1</manvolnum>
++                <refmiscinfo class="manual">User Commands</refmiscinfo>
++        </refmeta>
++
++        <refnamediv>
++                <refname>plymouth-set-default-theme</refname>
++                <refpurpose>Set the plymouth theme</refpurpose>
++        </refnamediv>
++
++        <refsynopsisdiv>
++                <cmdsynopsis>
++                        <command>plymouth-set-default-theme <arg choice="opt" rep="repeat">OPTION</arg> <arg choice="opt" rep="norepeat">THEME</arg></command>
++                </cmdsynopsis>
++        </refsynopsisdiv>
++
++        <refsect1>
++                <title>Description</title>
++
++<para>
++When called with a <option>THEME</option> argument,
++the <command>plymouth-set-default-theme</command> command
++changes the preferred boot theme and also performs the necessary
++regeneration of the initial ramdisk (initrd) since plymouth is loaded
++from the boot loader from the initrd prior to the mounting of the root
++filesystem.
++</para>
++
++<para>
++If <command>plymouth-set-default-theme</command> is invoked with no options
++or parameters, it shows the currently selected theme by default. This output
++is used by the helper scripts plymouth-generate-initrd and
++plymouth-update-initrd to set the proper theme in the initial ramdisk.
++</para>
++
++        </refsect1>
++
++        <refsect1>
++                <title>Options</title>
++
++                <para>The following options are understood:</para>
++
++                <variablelist>
++                        <varlistentry>
++                                <term><option>-h</option>, <option>--help</option></term>
++                                <listitem><para>Show summary of options.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>-l</option>, <option>--list</option></term>
++                                <listitem><para>List available themes.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>-r</option>, <option>--reset</option></term>
++                                <listitem><para>Reset to default theme.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>-R</option>, <option>--rebuild-initrd</option></term>
++                                <listitem><para>Rebuild initrd (necessary after changing theme).</para></listitem>
++                        </varlistentry>
++                </variablelist>
++        </refsect1>
++
++        <refsect1>
++                <title>See Also</title>
++                <para>
++                        <citerefentry><refentrytitle>grub</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++                        <citerefentry><refentrytitle>plymouth</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++                        <citerefentry><refentrytitle>plymouthd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++                        <citerefentry><refentrytitle>plymouth</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
++                        <ulink url="http://www.freedesktop.org/wiki/Software/Plymouth">http://www.freedesktop.org/wiki/Software/Plymouth</ulink>
++                </para>
++        </refsect1>
++
++</refentry>
+diff --git a/docs/plymouth.8 b/docs/plymouth.8
+deleted file mode 100644
+index 7f4766b..0000000
+--- a/docs/plymouth.8
++++ /dev/null
+@@ -1,62 +0,0 @@
+-\"                                      Hey, EMACS: -*- nroff -*-
+-.TH PLYMOUTH 8 "December 15, 2009"
+-.SH NAME
+-plymouth \- A graphical boot system and logger
+-.SH SYNOPSIS
+-.B plymouth-set-default-theme
+-.RI [ options ] " \<theme\>"
+-.SH DESCRIPTION
+-\fBplymouth\fP is a graphical boot system for Linux which takes advantage of the kernel-based
+-mode setting (KMS) available for modern graphic cards to provide a seamless, flickerfree
+-and attractive boot screen. It allows to choose between various, static or
+-animated graphical themes to spruce up the startup and avoid the noise
+-generated by the vast amount of kernel messages while the machine boots into X.
+-On systems where kernel-based mode setting is not available, plymouth falls
+-back to a text mode boot screen which provides a simple progress bar to provide
+-feedback during boot.
+-.PP
+-To configure plymouth, that is to choose and install the preferred boot theme, the
+-user has to invoke \fBplymouth-set-default-theme\fP. It changes the configuration
+-to the new theme and also performs the necessary regeneration of the initial ramdisk
+-(initrd) since plymouth is loaded from the boot loader from the initrd
+-prior to the mounting of the root filesystem. The options available to this
+-script are explained in the \fBOPTIONS\fP paragraph.
+-.PP
+-In order for the configured default plymouth theme to be loaded during boot,
+-the option `splash' (or `rhgb' for backward compatibility with the RHGB boot
+-splash) must be provided at the kernel command line.  With this command line
+-option, plymouth will default to showing detailed boot output.
+-.SH OPTIONS
+-plymouth-set-default-theme follows the usual GNU command line syntax, with long
+-options starting with two dashes (`-') and short variants of each of them.
+-.TP
+-.B \-h, \-\-help
+-Show summary of options.
+-.TP
+-.B \-l, \-\-list
+-List available themes.
+-.TP
+-.B \-r, \-\-reset
+-Reset to default theme.
+-.TP
+-.B \-R, \-\-rebuild\-initrd
+-Rebuild initrd (necessary after changing theme).
+-.TP
+-.B \<theme-name\>
+-Name of new theme to use. If you want to see which themes are available, invoke the script with just \-\-list.
+-.PP
+-If plymouth-set-default-theme is invoked with no options or parameters, it shows the currently selected theme
+-by default. This output is used by the helper scripts `plymouth-generate-initrd' and `plymouth-update-initrd'
+-to set the proper theme in the initial ramdisk.
+-.SH SEE ALSO
+-.BR grub (8)
+-.br
+-.SH AUTHOR
+-plymouth was originally prototyped and named by Kristian Høgsberg <krh at bitplanet.net>,
+-originally written by Ray Strode <halfline at gmail.com> and has had significant contributions
+-from Charlie Brej <cbrej at cs.man.ac.uk>.  It has also had contributions from
+-Peter Jones <pjones at redhat.com>, Adam Jackson <ajax at nwnk.net>,
+-Frederic Crozat <fcrozat at mandriva.com> and others.
+-It can be downloaded here: <http://www.freedesktop.org/wiki/Software/Plymouth>.
+-.PP
+-This manual page was written by Adrian Glaubitz <glaubitz at physik.fu-berlin.de>.
+diff --git a/docs/plymouth.xml b/docs/plymouth.xml
+new file mode 100644
+index 0000000..0f196c6
+--- /dev/null
++++ b/docs/plymouth.xml
+@@ -0,0 +1,86 @@
++<?xml version='1.0'?>
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
++        "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
++
++<refentry id="plymouth">
++
++        <refentryinfo>
++                <title>plymouth</title>
++                <productname>plymouth</productname>
++
++                <authorgroup>
++                        <author>
++                                <contrib>Developer</contrib>
++                                <firstname>Kristian</firstname>
++                                <surname>Høgsberg</surname>
++                        </author>
++                        <author>
++                                <contrib>Developer</contrib>
++                                <firstname>Ray</firstname>
++                                <surname>Strode</surname>
++                        </author>
++                </authorgroup>
++
++        </refentryinfo>
++
++        <refmeta>
++                <refentrytitle>plymouth</refentrytitle>
++                <manvolnum>8</manvolnum>
++                <refmiscinfo class="manual">System Administration</refmiscinfo>
++        </refmeta>
++
++        <refnamediv>
++                <refname>plymouth</refname>
++                <refpurpose>A graphical boot system and logger</refpurpose>
++        </refnamediv>
++
++        <refsect1>
++                <title>Description</title>
++
++<para>
++<command>plymouth</command> is a graphical boot system for Linux which takes advantage of
++the kernel-based mode setting (KMS) available for modern graphic  cards
++to  provide  a  seamless,  flickerfree  and  attractive boot screen. It
++allows to choose between various, static or animated  graphical  themes
++to  spruce  up  the  startup  and avoid the noise generated by the vast
++amount of kernel messages while the machine boots into X.   On  systems
++where  kernel-based  mode setting is not available, plymouth falls back
++to a text mode boot screen which provides a simple progress bar to pro‐
++vide feedback during boot.
++</para>
++<para>
++In order for the configured default plymouth theme to be loaded during
++boot, the option `splash' (or `rhgb' for  backward  compatibility  with
++the RHGB  boot  splash) must be provided at the kernel command line.
++Without this command line option, plymouth will default to showing
++detailed boot output.
++</para>
++
++<para>
++During the boot process, the user can switch between the graphical theme
++and the detailed boot output using the Escape key.
++</para>
++
++        </refsect1>
++
++        <refsect1>
++                <title>See Also</title>
++                <para>
++                        <citerefentry><refentrytitle>grub</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++                        <citerefentry><refentrytitle>plymouth-set-theme</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
++                        <citerefentry><refentrytitle>plymouthd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++                        <citerefentry><refentrytitle>plymouth</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
++                        <ulink url="http://www.freedesktop.org/wiki/Software/Plymouth">http://www.freedesktop.org/wiki/Software/Plymouth</ulink>
++                </para>
++        </refsect1>
++
++        <refsect1>
++                <title>Authors</title>
++                <para>
++plymouth  was  originally  prototyped  and  named  by Kristian Høgsberg,
++originally written by Ray Strode and has had significant contributions from
++Charlie Brej. It has also had contributions from Peter Jones, Adam Jackson,
++Frederic Crozat and others.
++                </para>
++        </refsect1>
++</refentry>
+diff --git a/docs/plymouth1.xml b/docs/plymouth1.xml
+new file mode 100644
+index 0000000..b484599
+--- /dev/null
++++ b/docs/plymouth1.xml
+@@ -0,0 +1,351 @@
++<?xml version='1.0'?>
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
++        "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
++
++<refentry id="plymouth-set-default-theme">
++
++        <refentryinfo>
++                <title>plymouth</title>
++                <productname>plymouth</productname>
++
++                <authorgroup>
++                        <author>
++                                <contrib>Developer</contrib>
++                                <firstname>Kristian</firstname>
++                                <surname>Høgsberg</surname>
++                        </author>
++                        <author>
++                                <contrib>Developer</contrib>
++                                <firstname>Ray</firstname>
++                                <surname>Strode</surname>
++                        </author>
++                </authorgroup>
++
++        </refentryinfo>
++
++        <refmeta>
++                <refentrytitle>plymouth</refentrytitle>
++                <manvolnum>1</manvolnum>
++                <refmiscinfo class="manual">User Commands</refmiscinfo>
++        </refmeta>
++
++        <refnamediv>
++                <refname>plymouth</refname>
++                <refpurpose>Send commands to plymouthd</refpurpose>
++        </refnamediv>
++
++        <refsynopsisdiv>
++                <cmdsynopsis>
++                        <command>plymouth <arg choice="opt" rep="repeat">OPTION</arg></command>
++                </cmdsynopsis>
++                <cmdsynopsis>
++                        <command>plymouth <arg choice="plain">COMMAND <arg choice="opt" rep="repeat">OPTION</arg></arg></command>
++                </cmdsynopsis>
++        </refsynopsisdiv>
++
++        <refsect1>
++                <title>Description</title>
++
++<para>
++The <command>plymouth</command> sends commands to a running
++<command>plymouthd</command>. This is used during the boot
++process to control the display of the graphical boot splash.
++</para>
++
++        </refsect1>
++
++        <refsect1>
++                <title>Options</title>
++
++                <para>
++The following options are understood. These options are supported
++for compatibility with the old <command>rhgb-client</command> interface,
++and have been replaced by the commands that are described in the
++next section.
++</para>
++
++                <variablelist>
++                        <varlistentry>
++                                <term><option>--help</option></term>
++                                <listitem><para>Show summary of options.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--debug</option></term>
++                                <listitem><para>Enable verbose debug logging.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--get-splash-plugin-path</option></term>
++                                <listitem><para>Get directory where splash plugins are installed.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--newroot=<arg>STRING</arg></option></term>
++                                <listitem><para>Tell plymouthd that the new root filesystem is mounted.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--quit</option></term>
++                                <listitem><para>Tell plymouthd to quit.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--ping</option></term>
++                                <listitem><para>Check if plymouthd is running.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--has-active-vt</option></term>
++                                <listitem><para>Check if plymouthd has an active vt.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--sysinit</option></term>
++                                <listitem><para>Tell plymouthd root filesystem is mounted read-write.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--show-splash</option></term>
++                                <listitem><para>Show the splash screen.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--hide-splash</option></term>
++                                <listitem><para>Hide the splash screen.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--ask-for-password</option></term>
++                                <listitem><para>Ask the user for a password.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--ignore-keystroke=<arg>STRING</arg></option></term>
++                                <listitem><para>Remove sensitivity to a keystroke.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--update=<arg>STRING</arg></option></term>
++                                <listitem><para>Tell plymouthd an update about boot progress.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--details</option></term>
++                                <listitem><para>Tell plymouthd there were errors during boot.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--wait</option></term>
++                                <listitem><para>Wait for plymouthd to quit.</para></listitem>
++                        </varlistentry>
++                </variablelist>
++        </refsect1>
++
++        <refsect1>
++		<title>Commands</title>
++
++<para>
++The following commands are understood:
++</para>
++                <variablelist>
++                        <varlistentry>
++                                <term><command>change-mode <arg choice="plain">OPTION</arg></command></term>
++                                <listitem><para>Change the operation mode.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--boot-up</option></term>
++  <listitem><para>Start the system up</para></listitem>
++</varlistentry>
++<varlistentry>
++  <term><option>--shutdown</option></term>
++  <listitem><para>Shutting the system up</para></listitem>
++</varlistentry>
++<varlistentry>
++  <term><option>--updates</option></term>
++  <listitem><para>Applying updates</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>system-update <arg choice="plain">OPTION</arg></command></term>
++                                <listitem><para>Tell plymouthd about boot progress.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--progress=INTEGER</option></term>
++  <listitem><para>The percentage progress of the updates</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>update <arg choice="plain">OPTION</arg></command></term>
++                                <listitem><para>Tell plymouthd about boot status changes.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--status=STRING</option></term>
++  <listitem><para>Tell plymouthd the current boot status</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>update-root-fs <arg choice="plain">OPTION</arg></command></term>
++                                <listitem><para>Tell plymouthd about root filesystem changes.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--new-root-dir=STRING</option></term>
++  <listitem><para>Root filesystem is about to change</para></listitem>
++</varlistentry>
++<varlistentry>
++  <term><option>--read-write</option></term>
++  <listitem><para>Root filesystem is no longer read-only</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>show-splash</command></term>
++                                <listitem><para>Tell plymouthd to show splash screen.</para></listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>hide-splash</command></term>
++                                <listitem><para>Tell plymouthd to hide splash screen.</para></listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>ask-for-password <arg choice="plain">OPTION</arg></command></term>
++                                <listitem><para>Ask the user for a password.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--command=STRING</option></term>
++  <listitem><para>Command to send password to via standard input</para></listitem>
++</varlistentry>
++<varlistentry>
++  <term><option>--prompt=STRING</option></term>
++  <listitem><para>Message to display when asking for password</para></listitem>
++</varlistentry>
++<varlistentry>
++  <term><option>--number-of-tries=INTEGER</option></term>
++  <listitem><para>Number of times to ask before giving up (requires <option>--command</option>)</para></listitem>
++</varlistentry>
++<varlistentry>
++  <term><option>--dont-pause-progress</option></term>
++  <listitem><para>Don't pause boot progress bar while asking</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>ask-question</command></term>
++                                <listitem><para>Ask the user a question.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--command=STRING</option></term>
++  <listitem><para>Command to send the answer to via standard input</para></listitem>
++</varlistentry>
++<varlistentry>
++  <term><option>--prompt=STRING</option></term>
++  <listitem><para>Message to display when asking the question</para></listitem>
++</varlistentry>
++<varlistentry>
++  <term><option>--dont-pause-progress</option></term>
++  <listitem><para>Don't pause boot progress bar while asking</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>display-message <arg choice="plain">OPTION</arg></command></term>
++                                <listitem><para>Display a message.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--text=STRING</option></term>
++  <listitem><para>The message text</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>hide-message <arg choice="plain">OPTION</arg></command></term>
++                                <listitem><para>Hide a message.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--text=STRING</option></term>
++  <listitem><para>The message text</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>watch-keystroke <arg choice="plain">OPTION</arg></command></term>
++                                <listitem><para>Become sensitive to a keystroke.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--command=STRING</option></term>
++  <listitem><para>Command to send keystroke to via standard input</para></listitem>
++</varlistentry>
++<varlistentry>
++  <term><option>--keys=STRING</option></term>
++  <listitem><para>Keys to become sensitive to</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>ignore-keystroke <arg choice="plain">OPTION</arg></command></term>
++                                <listitem><para>Remove sensitivity to a keystroke.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--keys=STRING</option></term>
++  <listitem><para>Keys to remove sensitivitiy from</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>pause-progress</command></term>
++                                <listitem><para>Pause boot progress bar.</para></listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>unpause-progress</command></term>
++                                <listitem><para>Unpause boot progress bar.</para></listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>report-error</command></term>
++                                <listitem><para>Tell plymouthd there were errors during boot.</para></listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>deactivate</command></term>
++                                <listitem><para>Tell plymouthd to deactivate.</para></listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>reactivate</command></term>
++                                <listitem><para>Tell plymouthd to reactivate.</para></listitem>
++                        </varlistentry>
++                        <varlistentry>
++                                <term><command>quit <arg choice="plain">OPTION</arg></command></term>
++                                <listitem><para>Tell plymouthd to quit.</para>
++<variablelist>
++<varlistentry>
++  <term><option>--retain-splash</option></term>
++  <listitem><para>Don't explicitly hide boot splash on exit</para></listitem>
++</varlistentry>
++</variablelist>
++</listitem>
++                        </varlistentry>
++                </variablelist>
++
++        </refsect1>
++
++        <refsect1>
++                <title>See Also</title>
++                <para>
++                        <citerefentry><refentrytitle>grub</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++                        <citerefentry><refentrytitle>plymouth</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++                        <citerefentry><refentrytitle>plymouthd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++                        <ulink url="http://www.freedesktop.org/wiki/Software/Plymouth">http://www.freedesktop.org/wiki/Software/Plymouth</ulink>
++                </para>
++        </refsect1>
++
++</refentry>
+diff --git a/docs/plymouthd.xml b/docs/plymouthd.xml
+new file mode 100644
+index 0000000..4e7e499
+--- /dev/null
++++ b/docs/plymouthd.xml
+@@ -0,0 +1,121 @@
++<?xml version='1.0'?>
++<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
++        "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
++
++<refentry id="plymouthd">
++
++        <refentryinfo>
++                <title>plymouthd</title>
++                <productname>plymouth</productname>
++
++                <authorgroup>
++                        <author>
++                                <contrib>Developer</contrib>
++                                <firstname>Kristian</firstname>
++                                <surname>Høgsberg</surname>
++                        </author>
++                        <author>
++                                <contrib>Developer</contrib>
++                                <firstname>Ray</firstname>
++                                <surname>Strode</surname>
++                        </author>
++                </authorgroup>
++
++        </refentryinfo>
++
++        <refmeta>
++                <refentrytitle>plymouthd</refentrytitle>
++                <manvolnum>8</manvolnum>
++                <refmiscinfo class="manual">System Administration</refmiscinfo>
++        </refmeta>
++
++        <refnamediv>
++                <refname>plymouthd</refname>
++                <refpurpose>The plymouth daemon</refpurpose>
++        </refnamediv>
++
++        <refsynopsisdiv>
++                <cmdsynopsis>
++                        <command>plymouthd <arg choice="opt" rep="repeat">OPTION</arg></command>
++                </cmdsynopsis>
++        </refsynopsisdiv>
++
++        <refsect1>
++                <title>Description</title>
++
++<para>
++The <command>plymouthd</command> daemon is usually run out of
++the initrd. It does the heavy lifting of the plymouth system, logging
++the session and showing the splash screen.
++</para>
++<para>
++The <command>plymouth</command> is used to send commands to plymouthd
++that control its behaviour.
++</para>
++
++        </refsect1>
++
++        <refsect1>
++                <title>Options</title>
++
++                <para>The following options are understood:</para>
++
++                <variablelist>
++                        <varlistentry>
++                                <term><option>--help</option></term>
++                                <listitem><para>Show summary of options.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--attach-to-session</option></term>
++                                <listitem><para>Redirect console messages from screen to log.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--no-daemon</option></term>
++                                <listitem><para>Do not daemonize.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--debug</option></term>
++                                <listitem><para>Output debugging information.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--debug-file=STRING</option></term>
++                                <listitem><para>File to write debugging information to.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--mode=MODE</option></term>
++                                <listitem><para>Set mode to either boot or shutdown.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--pid-file=STRING</option></term>
++                                <listitem><para>Write the PID of the daemon to a file.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--kernel-command-line=STRING</option></term>
++                                <listitem><para>Fake kernel commandline to use.</para></listitem>
++                        </varlistentry>
++
++                        <varlistentry>
++                                <term><option>--tty=STRING</option></term>
++                                <listitem><para>TTY to ues instead of default.</para></listitem>
++                        </varlistentry>
++                </variablelist>
++        </refsect1>
++
++        <refsect1>
++                <title>See Also</title>
++                <para>
++                        <citerefentry><refentrytitle>grub</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++                        <citerefentry><refentrytitle>plymouth</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
++                        <citerefentry><refentrytitle>plymouth</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
++                        <ulink url="http://www.freedesktop.org/wiki/Software/Plymouth">http://www.freedesktop.org/wiki/Software/Plymouth</ulink>
++                </para>
++        </refsect1>
++
++</refentry>
+diff --git a/scripts/plymouth-generate-initrd.in b/scripts/plymouth-generate-initrd.in
+index 35509a1..c44ca4c 100755
+--- a/scripts/plymouth-generate-initrd.in
++++ b/scripts/plymouth-generate-initrd.in
+@@ -13,11 +13,12 @@ PLYMOUTH_INITRD_DIR="$(mktemp --tmpdir -d plymouth-XXXXXXX)"
+ $PLYMOUTH_POPULATE_INITRD -t "$PLYMOUTH_INITRD_DIR"
+ 
+ if [ $? -eq 0 ]; then
++    command -v pigz &>/dev/null && gzip=pigz || gzip=gzip
+     (cd $PLYMOUTH_INITRD_DIR;
+         # FIXME: might make sense to add a flag to plymouth-populate-initrd to
+         #        skip these from the start
+         rm -f lib*/{ld*,libc*,libdl*,libm*,libz*,libpthread*}
+-        find | cpio -Hnewc -o | gzip -9 > $PLYMOUTH_IMAGE_FILE
++        find | cpio -Hnewc -o | $gzip -9 > $PLYMOUTH_IMAGE_FILE
+     )
+ fi
+ 
+diff --git a/scripts/plymouth-populate-initrd.in b/scripts/plymouth-populate-initrd.in
+index 8d1eec0..43c7f22 100755
+--- a/scripts/plymouth-populate-initrd.in
++++ b/scripts/plymouth-populate-initrd.in
+@@ -8,6 +8,7 @@
+ [ -z "$PLYMOUTH_DATADIR" ] && PLYMOUTH_DATADIR="@PLYMOUTH_DATADIR@"
+ [ -z "$PLYMOUTH_PLUGIN_PATH" ] && PLYMOUTH_PLUGIN_PATH="$(plymouth --get-splash-plugin-path)"
+ [ -z "$PLYMOUTH_LOGO_FILE" ] && PLYMOUTH_LOGO_FILE="@PLYMOUTH_LOGO_FILE@"
++[ -n "$PLYMOUTH_THEME_NAME" ] && THEME_OVERRIDE=1
+ [ -z "$PLYMOUTH_THEME_NAME" ] && PLYMOUTH_THEME_NAME=$(plymouth-set-default-theme)
+ [ -z "$PLYMOUTH_CONFDIR" ] && PLYMOUTH_CONFDIR="@PLYMOUTH_CONF_DIR@"
+ [ -z "$PLYMOUTH_POLICYDIR" ] && PLYMOUTH_POLICYDIR="@PLYMOUTH_POLICY_DIR@"
+@@ -372,8 +373,8 @@ done
+ [ -z "$INITRDDIR" ] && usage error
+ 
+ mkdir -p ${INITRDDIR}${PLYMOUTH_DATADIR}/plymouth/themes
+-inst ${PLYMOUTH_DAEMON_PATH} $INITRDDIR /sbin/plymouthd
+-inst ${PLYMOUTH_CLIENT_PATH} $INITRDDIR /bin/plymouth
++inst ${PLYMOUTH_DAEMON_PATH} $INITRDDIR
++inst ${PLYMOUTH_CLIENT_PATH} $INITRDDIR
+ inst ${PLYMOUTH_DATADIR}/plymouth/themes/text/text.plymouth $INITRDDIR
+ inst ${PLYMOUTH_PLUGIN_PATH}/text.so $INITRDDIR
+ inst ${PLYMOUTH_DATADIR}/plymouth/themes/details/details.plymouth $INITRDDIR
+@@ -388,6 +389,12 @@ if [ -z "$PLYMOUTH_THEME_NAME" ]; then
+     exit 1
+ fi
+ 
++if [ $THEME_OVERRIDE ]; then
++    conf=$INITRDDIR/${PLYMOUTH_CONFDIR}/plymouthd.conf
++    echo "modifying plymouthd.conf: Theme=$PLYMOUTH_THEME_NAME" > /dev/stderr
++    sed -i "s/^ *Theme *=.*/# theme modified by plymouth-populate-initrd\nTheme=$PLYMOUTH_THEME_NAME/" $conf
++fi
++
+ PLYMOUTH_MODULE_NAME=$(grep "ModuleName *= *" ${PLYMOUTH_DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME}/${PLYMOUTH_THEME_NAME}.plymouth | sed 's/ModuleName *= *//')
+ 
+ if [ ! -f ${PLYMOUTH_PLUGIN_PATH}/${PLYMOUTH_MODULE_NAME}.so ]; then
+@@ -425,6 +432,7 @@ if [ -n "$SYSTEMD_UNIT_DIR" -a -d "$SYSTEMD_UNIT_DIR" ]; then
+     inst $SYSTEMD_UNIT_DIR/plymouth-halt.service $INITRDDIR
+ 
+     inst $SYSTEMD_UNIT_DIR/initrd-switch-root.target.wants/plymouth-switch-root.service $INITRDDIR
++    inst $SYSTEMD_UNIT_DIR/initrd-switch-root.target.wants/plymouth-start.service $INITRDDIR
+     inst $SYSTEMD_UNIT_DIR/sysinit.target.wants/plymouth-start.service $INITRDDIR
+     inst $SYSTEMD_UNIT_DIR/multi-user.target.wants/plymouth-quit.service $INITRDDIR
+     inst $SYSTEMD_UNIT_DIR/multi-user.target.wants/plymouth-quit-wait.service $INITRDDIR
+diff --git a/scripts/plymouth-update-initrd b/scripts/plymouth-update-initrd
+index 1403b8b..4ed5709 100755
+--- a/scripts/plymouth-update-initrd
++++ b/scripts/plymouth-update-initrd
+@@ -1,2 +1,2 @@
+ #!/bin/bash
+-mkinitrd -f /boot/initrd-$(uname -r).img $(uname -r)
++dracut -f
+diff --git a/src/Makefile.am b/src/Makefile.am
+index a9e6eb1..fc2f5da 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -1,8 +1,8 @@
+-SUBDIRS = libply libply-splash-core libply-splash-graphics . plugins client viewer tests
++SUBDIRS = libply libply-splash-core libply-splash-graphics . plugins client viewer
+ if ENABLE_UPSTART_MONITORING
+ SUBDIRS += upstart-bridge
+ endif
+-INCLUDES = -I$(top_srcdir)                                                    \
++AM_CPPFLAGS = -I$(top_srcdir)                                                 \
+            -I$(srcdir)/libply                                                 \
+            -I$(srcdir)/libply-splash-core                                     \
+            -I$(srcdir)                                                        \
+@@ -15,6 +15,7 @@ plymouthdbindir = $(plymouthdaemondir)
+ plymouthdbin_PROGRAMS = plymouthd
+ 
+ plymouthd_CFLAGS = $(PLYMOUTH_CFLAGS)                                         \
++		   -rdynamic                                                  \
+ 		   -DPLYMOUTH_PLUGIN_PATH=\"$(PLYMOUTH_PLUGIN_PATH)\"         \
+ 		   -DPLYMOUTH_THEME_PATH=\"$(PLYMOUTH_THEME_PATH)/\"          \
+ 		   -DPLYMOUTH_POLICY_DIR=\"$(PLYMOUTH_POLICY_DIR)/\"          \
+diff --git a/src/client/Makefile.am b/src/client/Makefile.am
+index 9487901..83b19cc 100644
+--- a/src/client/Makefile.am
++++ b/src/client/Makefile.am
+@@ -1,6 +1,4 @@
+-SUBDIRS = . tests
+-
+-INCLUDES = -I$(top_srcdir)                                                    \
++AM_CPPFLAGS = -I$(top_srcdir)                                                 \
+            -I$(top_srcdir)/src                                                \
+            -I$(top_srcdir)/src/libply                                         \
+            -I$(srcdir)
+diff --git a/src/client/ply-boot-client.c b/src/client/ply-boot-client.c
+index 56458ce..3480676 100644
+--- a/src/client/ply-boot-client.c
++++ b/src/client/ply-boot-client.c
+@@ -869,137 +869,4 @@ ply_boot_client_attach_to_event_loop (ply_boot_client_t *client,
+ 
+ }
+ 
+-#ifdef PLY_BOOT_CLIENT_ENABLE_TEST
+-
+-#include <stdio.h>
+-
+-#include "ply-event-loop.h"
+-#include "ply-boot-client.h"
+-
+-static void
+-on_pinged (ply_event_loop_t *loop)
+-{
+-  printf ("PING!\n");
+-}
+-
+-static void
+-on_ping_failed (ply_event_loop_t *loop)
+-{
+-  printf ("PING FAILED! %m\n");
+-  ply_event_loop_exit (loop, 1);
+-}
+-
+-static void
+-on_update (ply_event_loop_t *loop)
+-{
+-  printf ("UPDATE!\n");
+-}
+-
+-static void
+-on_update_failed (ply_event_loop_t *loop)
+-{
+-  printf ("UPDATE FAILED! %m\n");
+-  ply_event_loop_exit (loop, 1);
+-}
+-
+-static void
+-on_newroot (ply_event_loop_t *loop)
+-{
+-  printf ("NEWROOT!\n");
+-}
+-
+-static void
+-on_system_initialized (ply_event_loop_t *loop)
+-{
+-  printf ("SYSTEM INITIALIZED!\n");
+-}
+-
+-static void
+-on_system_initialized_failed (ply_event_loop_t *loop)
+-{
+-  printf ("SYSTEM INITIALIZATION REQUEST FAILED!\n");
+-  ply_event_loop_exit (loop, 1);
+-}
+-
+-static void
+-on_quit (ply_event_loop_t *loop)
+-{
+-  printf ("QUIT!\n");
+-  ply_event_loop_exit (loop, 0);
+-}
+-
+-static void
+-on_quit_failed (ply_event_loop_t *loop)
+-{
+-  printf ("QUIT FAILED! %m\n");
+-  ply_event_loop_exit (loop, 2);
+-}
+-
+-static void
+-on_disconnect (ply_event_loop_t *loop)
+-{
+-  printf ("DISCONNECT!\n");
+-  ply_event_loop_exit (loop, 1);
+-}
+-
+-int
+-main (int    argc,
+-      char **argv)
+-{
+-  ply_event_loop_t *loop;
+-  ply_boot_client_t *client;
+-  int exit_code;
+-
+-  exit_code = 0;
+-
+-  loop = ply_event_loop_new ();
+-
+-  client = ply_boot_client_new ();
+-
+-  if (!ply_boot_client_connect (client, 
+-                                (ply_boot_client_disconnect_handler_t) on_disconnect,
+-                                loop))
+-    {
+-      perror ("could not start boot client");
+-      return errno;
+-    }
+-
+-  ply_boot_client_attach_to_event_loop (client, loop);
+-  ply_boot_client_ping_daemon (client, 
+-                               (ply_boot_client_response_handler_t) on_pinged,
+-                               (ply_boot_client_response_handler_t) on_ping_failed,
+-                               loop);
+-
+-  ply_boot_client_update_daemon (client, 
+-                                 "loading",
+-                                 (ply_boot_client_response_handler_t) on_update,
+-                                 (ply_boot_client_response_handler_t) on_update_failed,
+-                                 loop);
+-
+-  ply_boot_client_update_daemon (client, 
+-                                 "loading more",
+-                                 (ply_boot_client_response_handler_t) on_update,
+-                                 (ply_boot_client_response_handler_t) on_update_failed,
+-                                 loop);
+-
+-  ply_boot_client_tell_daemon_system_is_initialized (client, 
+-                                       (ply_boot_client_response_handler_t) 
+-                                       on_system_initialized,
+-                                       (ply_boot_client_response_handler_t) 
+-                                       on_system_initialized_failed,
+-                                       loop);
+-
+-  ply_boot_client_tell_daemon_to_quit (client, 
+-                                       (ply_boot_client_response_handler_t) on_quit,
+-                                       (ply_boot_client_response_handler_t) on_quit_failed,
+-                                       loop);
+-
+-  exit_code = ply_event_loop_run (loop);
+-
+-  ply_boot_client_free (client);
+-
+-  return exit_code;
+-}
+-
+-#endif /* PLY_BOOT_CLIENT_ENABLE_TEST */
+ /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
+diff --git a/src/client/plymouth.c b/src/client/plymouth.c
+index e00208d..b22e90c 100644
+--- a/src/client/plymouth.c
++++ b/src/client/plymouth.c
+@@ -1173,7 +1173,8 @@ main (int    argc,
+ 
+   if (get_kernel_command_line (&state))
+     {
+-      if (strstr (state.kernel_command_line, "plymouth:debug") != NULL
++      if ((strstr (state.kernel_command_line, "plymouth.debug") != NULL ||
++           strstr (state.kernel_command_line, "plymouth:debug") != NULL)
+           && !ply_is_tracing ())
+         ply_toggle_tracing ();
+     }
+diff --git a/src/client/tests/Makefile.am b/src/client/tests/Makefile.am
+deleted file mode 100644
+index c6dbfdb..0000000
+--- a/src/client/tests/Makefile.am
++++ /dev/null
+@@ -1,10 +0,0 @@
+-INCLUDES =                                                                    \
+-           -I$(top_srcdir)                                                    \
+-           -I$(srcdir)/..                                                     \
+-           -I$(srcdir)/../..                                                  \
+-           -I$(srcdir)
+-TESTS = 
+-
+-noinst_PROGRAMS = $(TESTS)
+-
+-MAINTAINERCLEANFILES = Makefile.in
+diff --git a/src/libply-splash-core/Makefile.am b/src/libply-splash-core/Makefile.am
+index b289b65..d07d7f1 100644
+--- a/src/libply-splash-core/Makefile.am
++++ b/src/libply-splash-core/Makefile.am
+@@ -1,4 +1,4 @@
+-INCLUDES = -I$(top_srcdir)                                                    \
++AM_CPPFLAGS = -I$(top_srcdir)                                                 \
+            -I$(srcdir)                                                        \
+            -I$(srcdir)/../libply                                              \
+            -I$(srcdir)/../plugins/controls
+@@ -15,33 +15,39 @@ libply_splash_coredir = $(includedir)/plymouth-1/ply-splash-core
+ libply_splash_core_HEADERS = \
+ 		    ply-boot-splash.h                                         \
+ 		    ply-boot-splash-plugin.h                                  \
++		    ply-device-manager.h                                      \
+ 		    ply-keyboard.h                                            \
+ 		    ply-pixel-buffer.h                                        \
+ 		    ply-pixel-display.h                                       \
+ 		    ply-renderer.h                                            \
+ 		    ply-renderer-plugin.h                                     \
++		    ply-seat.h                                                \
+ 		    ply-terminal.h                                            \
+ 		    ply-text-display.h                                        \
+-		    ply-text-progress-bar.h
++		    ply-text-progress-bar.h                                   \
++		    ply-text-step-bar.h
+ 
+-libply_splash_core_la_CFLAGS = $(PLYMOUTH_CFLAGS)                               \
++libply_splash_core_la_CFLAGS = $(PLYMOUTH_CFLAGS) $(UDEV_CFLAGS)               \
+                              -DPLYMOUTH_BACKGROUND_COLOR=$(background_color)   \
+                        -DPLYMOUTH_BACKGROUND_END_COLOR=$(background_end_color) \
+                        -DPLYMOUTH_BACKGROUND_START_COLOR=$(background_start_color) \
+                        -DPLYMOUTH_PLUGIN_PATH=\"$(PLYMOUTH_PLUGIN_PATH)\"
+-libply_splash_core_la_LIBADD = $(PLYMOUTH_LIBS) ../libply/libply.la
++libply_splash_core_la_LIBADD = $(PLYMOUTH_LIBS) $(UDEV_LIBS) ../libply/libply.la
+ libply_splash_core_la_LDFLAGS = -export-symbols-regex '^[^_].*' \
+ 		    -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ 		    -no-undefined
+ libply_splash_core_la_SOURCES = \
+ 		    $(libply_splash_core_HEADERS)                              \
++		    ply-device-manager.c                                      \
+ 		    ply-keyboard.c                                           \
+ 		    ply-pixel-display.c                                      \
+ 		    ply-text-display.c                                       \
+ 		    ply-text-progress-bar.c                                  \
++		    ply-text-step-bar.c                                      \
+ 		    ply-terminal.c                                           \
+ 		    ply-pixel-buffer.c                                       \
+ 		    ply-renderer.c                                           \
++		    ply-seat.c                                               \
+ 		    ply-boot-splash.c
+ 
+ MAINTAINERCLEANFILES = Makefile.in
+diff --git a/src/libply-splash-core/ply-boot-splash.c b/src/libply-splash-core/ply-boot-splash.c
+index 93d9345..160ce45 100644
+--- a/src/libply-splash-core/ply-boot-splash.c
++++ b/src/libply-splash-core/ply-boot-splash.c
+@@ -48,10 +48,6 @@
+ #define UPDATES_PER_SECOND 30
+ #endif
+ 
+-#define KEY_CTRL_L ('\100' ^'L')
+-#define KEY_CTRL_T ('\100' ^'T')
+-#define KEY_CTRL_V ('\100' ^'V')
+-
+ struct _ply_boot_splash
+ {
+   ply_event_loop_t *loop;
+@@ -59,11 +55,9 @@ struct _ply_boot_splash
+   const ply_boot_splash_plugin_interface_t *plugin_interface;
+   ply_boot_splash_plugin_t *plugin;
+   ply_boot_splash_mode_t mode;
+-  ply_keyboard_t *keyboard;
+   ply_buffer_t *boot_buffer;
+   ply_trigger_t *idle_trigger;
+-  ply_list_t *pixel_displays;
+-  ply_list_t *text_displays;
++  ply_list_t *seats;
+ 
+   char *theme_path;
+   char *plugin_dir;
+@@ -100,18 +94,30 @@ ply_boot_splash_new (const char     *theme_path,
+   splash->mode = PLY_BOOT_SPLASH_MODE_INVALID;
+ 
+   splash->boot_buffer = boot_buffer;
+-  splash->pixel_displays = ply_list_new ();
+-  splash->text_displays = ply_list_new ();
++  splash->seats = ply_list_new ();
+ 
+   return splash;
+ }
+ 
+ static void
+-refresh_displays (ply_boot_splash_t *splash)
++detach_from_seat (ply_boot_splash_t *splash,
++                  ply_seat_t        *seat)
+ {
+-  ply_list_node_t *node;
++  ply_keyboard_t *keyboard;
++  ply_list_t *displays;
++  ply_list_node_t *node, *next_node;
+ 
+-  node = ply_list_get_first_node (splash->pixel_displays);
++  ply_trace ("removing keyboard");
++  if (splash->plugin_interface->unset_keyboard != NULL)
++    {
++      keyboard = ply_seat_get_keyboard (seat);
++      splash->plugin_interface->unset_keyboard (splash->plugin, keyboard);
++    }
++
++  ply_trace ("removing pixel displays");
++  displays = ply_seat_get_pixel_displays (seat);
++
++  node = ply_list_get_first_node (displays);
+   while (node != NULL)
+     {
+       ply_pixel_display_t *display;
+@@ -119,184 +125,137 @@ refresh_displays (ply_boot_splash_t *splash)
+       unsigned long width, height;
+ 
+       display = ply_list_node_get_data (node);
+-      next_node = ply_list_get_next_node (splash->pixel_displays, node);
++      next_node = ply_list_get_next_node (displays, node);
+ 
+       width = ply_pixel_display_get_width (display);
+       height = ply_pixel_display_get_height (display);
+ 
+-      ply_pixel_display_draw_area (display, 0, 0, width, height);
++      ply_trace ("Removing %lux%lu pixel display", width, height);
++
++      if (splash->plugin_interface->remove_pixel_display != NULL)
++        splash->plugin_interface->remove_pixel_display (splash->plugin, display);
++
+       node = next_node;
+     }
+ 
+-  node = ply_list_get_first_node (splash->text_displays);
++  ply_trace ("removing text displays");
++  displays = ply_seat_get_text_displays (seat);
++
++  node = ply_list_get_first_node (displays);
+   while (node != NULL)
+     {
+       ply_text_display_t *display;
+-      ply_list_node_t *next_node;
+       int number_of_columns, number_of_rows;
+ 
+       display = ply_list_node_get_data (node);
+-      next_node = ply_list_get_next_node (splash->text_displays, node);
++      next_node = ply_list_get_next_node (displays, node);
+ 
+       number_of_columns = ply_text_display_get_number_of_columns (display);
+       number_of_rows = ply_text_display_get_number_of_rows (display);
+ 
+-      ply_text_display_draw_area (display, 0, 0,
+-                                  number_of_columns,
+-                                  number_of_rows);
++      ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows);
++
++      if (splash->plugin_interface->remove_text_display != NULL)
++        splash->plugin_interface->remove_text_display (splash->plugin, display);
++
+       node = next_node;
+     }
+ }
+ 
+-static ply_terminal_t *
+-find_local_console_terminal (ply_boot_splash_t *splash)
++static void
++attach_to_seat (ply_boot_splash_t *splash,
++                ply_seat_t        *seat)
+ {
+-  ply_list_node_t *node;
+-  node = ply_list_get_first_node (splash->text_displays);
++  ply_keyboard_t *keyboard;
++  ply_list_t *displays;
++  ply_list_node_t *node, *next_node;
+ 
+-  while (node != NULL)
++  if (splash->plugin_interface->set_keyboard != NULL)
+     {
+-      ply_text_display_t *display;
+-      ply_terminal_t *terminal;
+-      ply_list_node_t *next_node;
++      keyboard = ply_seat_get_keyboard (seat);
++      splash->plugin_interface->set_keyboard (splash->plugin, keyboard);
++    }
+ 
+-      display = ply_list_node_get_data (node);
+-      next_node = ply_list_get_next_node (splash->text_displays, node);
++  if (splash->plugin_interface->add_pixel_display != NULL)
++    {
++      displays = ply_seat_get_pixel_displays (seat);
+ 
+-      terminal = ply_text_display_get_terminal (display);
++      ply_trace ("adding pixel displays");
++      node = ply_list_get_first_node (displays);
++      while (node != NULL)
++        {
++          ply_pixel_display_t *display;
++          ply_list_node_t *next_node;
++          unsigned long width, height;
+ 
+-      if (terminal != NULL && ply_terminal_is_vt (terminal))
+-        return terminal;
++          display = ply_list_node_get_data (node);
++          next_node = ply_list_get_next_node (displays, node);
+ 
+-      node = next_node;
+-    }
++          width = ply_pixel_display_get_width (display);
++          height = ply_pixel_display_get_height (display);
+ 
+-  return NULL;
+-}
++          ply_trace ("Adding %lux%lu pixel display", width, height);
+ 
+-static void
+-on_keyboard_input (ply_boot_splash_t *splash,
+-                   const char        *keyboard_input,
+-                   size_t             character_size)
+-{
+-  wchar_t key;
++          splash->plugin_interface->add_pixel_display (splash->plugin, display);
+ 
+-  if ((ssize_t) mbrtowc (&key, keyboard_input, character_size, NULL) > 0)
+-    {
+-      switch (key)
+-        {
+-          case KEY_CTRL_L:
+-            refresh_displays (splash);
+-          return;
+-
+-          case KEY_CTRL_T:
+-            ply_trace ("toggle text mode!");
+-            splash->should_force_text_mode = !splash->should_force_text_mode;
+-
+-            if (ply_list_get_length (splash->pixel_displays) >= 1)
+-              {
+-                ply_terminal_t *terminal;
+-
+-                terminal = find_local_console_terminal (splash);
+-
+-                if (terminal != NULL)
+-                  {
+-                    if (splash->should_force_text_mode)
+-                      {
+-                        ply_terminal_set_mode (terminal, PLY_TERMINAL_MODE_TEXT);
+-                        ply_terminal_ignore_mode_changes (terminal, true);
+-                      }
+-                    else
+-                      ply_terminal_ignore_mode_changes (terminal, false);
+-                  }
+-              }
+-            ply_trace ("text mode toggled!");
+-          return;
+-
+-          case KEY_CTRL_V:
+-            ply_trace ("toggle verbose mode!");
+-            ply_toggle_tracing ();
+-            ply_trace ("verbose mode toggled!");
+-          return;
++          node = next_node;
+         }
+     }
+-}
+ 
+-void
+-ply_boot_splash_set_keyboard (ply_boot_splash_t *splash,
+-                              ply_keyboard_t    *keyboard)
+-{
+-  splash->keyboard = keyboard;
++  if (splash->plugin_interface->add_text_display != NULL)
++    {
++      displays = ply_seat_get_text_displays (seat);
+ 
+-  ply_keyboard_add_input_handler (keyboard,
+-                                  (ply_keyboard_input_handler_t)
+-                                  on_keyboard_input, splash);
++      ply_trace ("adding text displays");
++      node = ply_list_get_first_node (displays);
++      while (node != NULL)
++        {
++          ply_text_display_t *display;
++          int number_of_columns, number_of_rows;
+ 
+-  if (splash->plugin_interface->set_keyboard == NULL)
+-    return;
++          display = ply_list_node_get_data (node);
++          next_node = ply_list_get_next_node (displays, node);
+ 
+-  splash->plugin_interface->set_keyboard (splash->plugin, keyboard);
+-}
++          number_of_columns = ply_text_display_get_number_of_columns (display);
++          number_of_rows = ply_text_display_get_number_of_rows (display);
+ 
+-void
+-ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash)
+-{
+-  ply_keyboard_remove_input_handler (splash->keyboard,
+-                                     (ply_keyboard_input_handler_t)
+-                                     on_keyboard_input);
++          ply_trace ("Adding %dx%d text display", number_of_columns, number_of_rows);
+ 
+-  if (splash->plugin_interface->set_keyboard == NULL)
+-    return;
++          splash->plugin_interface->add_text_display (splash->plugin, display);
+ 
+-  splash->plugin_interface->unset_keyboard (splash->plugin, splash->keyboard);
++          node = next_node;
++        }
++    }
+ }
+ 
+ void
+-ply_boot_splash_add_pixel_display (ply_boot_splash_t   *splash,
+-                                   ply_pixel_display_t *display)
++ply_boot_splash_attach_to_seat (ply_boot_splash_t *splash,
++                                ply_seat_t        *seat)
+ {
+-  ply_list_append_data (splash->pixel_displays, display);
+-
+-  if (splash->plugin_interface->add_pixel_display == NULL)
+-    return;
+-
+-  splash->plugin_interface->add_pixel_display (splash->plugin, display);
+-}
++  ply_list_node_t *node;
+ 
+-void
+-ply_boot_splash_remove_pixel_display (ply_boot_splash_t   *splash,
+-                                      ply_pixel_display_t *display)
+-{
+-  ply_list_remove_data (splash->pixel_displays, display);
++  node = ply_list_find_node (splash->seats, seat);
+ 
+-  if (splash->plugin_interface->remove_pixel_display == NULL)
++  if (node != NULL)
+     return;
+ 
+-  splash->plugin_interface->remove_pixel_display (splash->plugin, display);
++  ply_list_append_data (splash->seats, seat);
++  attach_to_seat (splash, seat);
+ }
+ 
+ void
+-ply_boot_splash_add_text_display (ply_boot_splash_t   *splash,
+-                                  ply_text_display_t *display)
++ply_boot_splash_detach_from_seat (ply_boot_splash_t *splash,
++                                  ply_seat_t        *seat)
+ {
+-  ply_list_append_data (splash->text_displays, display);
++  ply_list_node_t *node;
+ 
+-  if (splash->plugin_interface->add_text_display == NULL)
+-    return;
++  node = ply_list_find_node (splash->seats, seat);
+ 
+-  splash->plugin_interface->add_text_display (splash->plugin, display);
+-}
+-
+-void
+-ply_boot_splash_remove_text_display (ply_boot_splash_t   *splash,
+-                                     ply_text_display_t *display)
+-{
+-  ply_list_remove_data (splash->text_displays, display);
+-
+-  if (splash->plugin_interface->remove_pixel_display == NULL)
++  if (node == NULL)
+     return;
+ 
+-  splash->plugin_interface->remove_text_display (splash->plugin, display);
++  ply_list_remove_data (splash->seats, seat);
++  detach_from_seat (splash, seat);
+ }
+ 
+ bool
+@@ -432,56 +391,24 @@ ply_boot_splash_unload (ply_boot_splash_t *splash)
+ }
+ 
+ static void
+-remove_displays (ply_boot_splash_t *splash)
++detach_from_seats (ply_boot_splash_t *splash)
+ {
+-  ply_list_node_t *node, *next_node;
++  ply_list_node_t *node;
+ 
+-  ply_trace ("removing pixel displays");
++  ply_trace ("detaching from seats");
+ 
+-  node = ply_list_get_first_node (splash->pixel_displays);
++  node = ply_list_get_first_node (splash->seats);
+   while (node != NULL)
+     {
+-      ply_pixel_display_t *display;
++      ply_seat_t *seat;
+       ply_list_node_t *next_node;
+-      unsigned long width, height;
+ 
+-      display = ply_list_node_get_data (node);
+-      next_node = ply_list_get_next_node (splash->pixel_displays, node);
++      seat = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (splash->seats, node);
+ 
+-      width = ply_pixel_display_get_width (display);
+-      height = ply_pixel_display_get_height (display);
++      detach_from_seat (splash, seat);
+ 
+-      ply_trace ("Removing %lux%lu pixel display", width, height);
+-
+-      if (splash->plugin_interface->remove_pixel_display != NULL)
+-        splash->plugin_interface->remove_pixel_display (splash->plugin, display);
+-
+-      ply_trace ("Removing node");
+-      ply_list_remove_node (splash->pixel_displays, node);
+-
+-      node = next_node;
+-    }
+-
+-  ply_trace ("removing text displays");
+-  node = ply_list_get_first_node (splash->text_displays);
+-  while (node != NULL)
+-    {
+-      ply_text_display_t *display;
+-      int number_of_columns, number_of_rows;
+-
+-      display = ply_list_node_get_data (node);
+-      next_node = ply_list_get_next_node (splash->text_displays, node);
+-
+-      number_of_columns = ply_text_display_get_number_of_columns (display);
+-      number_of_rows = ply_text_display_get_number_of_rows (display);
+-
+-      ply_trace ("Removing %dx%d text display", number_of_columns, number_of_rows);
+-
+-      if (splash->plugin_interface->remove_text_display != NULL)
+-        splash->plugin_interface->remove_text_display (splash->plugin, display);
+-
+-      ply_trace ("Removing node");
+-      ply_list_remove_node (splash->text_displays, node);
++      ply_list_remove_node (splash->seats, node);
+ 
+       node = next_node;
+     }
+@@ -508,9 +435,8 @@ ply_boot_splash_free (ply_boot_splash_t *splash)
+                                              splash);
+     }
+ 
+-  remove_displays (splash);
+-  ply_list_free (splash->pixel_displays);
+-  ply_list_free (splash->text_displays);
++  detach_from_seats (splash);
++  ply_list_free (splash->seats);
+ 
+   if (splash->module_handle != NULL)
+     ply_boot_splash_unload (splash);
+@@ -676,16 +602,6 @@ ply_boot_splash_hide (ply_boot_splash_t *splash)
+   splash->plugin_interface->hide_splash_screen (splash->plugin,
+                                                 splash->loop);
+ 
+-  if (ply_list_get_length (splash->pixel_displays) >= 1)
+-    {
+-      ply_terminal_t *terminal;
+-
+-      terminal = find_local_console_terminal (splash);
+-
+-      if (terminal != NULL)
+-        ply_terminal_set_mode (terminal, PLY_TERMINAL_MODE_TEXT);
+-    }
+-
+   splash->mode = PLY_BOOT_SPLASH_MODE_INVALID;
+ 
+   if (splash->loop != NULL)
+@@ -820,148 +736,4 @@ ply_boot_splash_become_idle (ply_boot_splash_t                  *splash,
+   splash->plugin_interface->become_idle (splash->plugin, splash->idle_trigger);
+ }
+ 
+-#ifdef PLY_BOOT_SPLASH_ENABLE_TEST
+-
+-#include <stdio.h>
+-
+-#include "ply-event-loop.h"
+-#include "ply-boot-splash.h"
+-
+-typedef struct test_state test_state_t;
+-struct test_state {
+-  ply_event_loop_t *loop;
+-  ply_boot_splash_t *splash;
+-  ply_buffer_t *buffer;
+-};
+-
+-static void
+-on_timeout (ply_boot_splash_t *splash)
+-{
+-  ply_boot_splash_update_status (splash, "foo");
+-  ply_event_loop_watch_for_timeout (splash->loop, 
+-                                    5.0,
+-                                   (ply_event_loop_timeout_handler_t)
+-                                   on_timeout,
+-                                   splash);
+-}
+-
+-static void
+-on_quit (test_state_t *state)
+-{
+-    ply_boot_splash_hide (state->splash);
+-    ply_event_loop_exit (state->loop, 0);
+-}
+-
+-static void
+-add_displays_to_splash_from_renderer (test_state_t   *state,
+-                                      ply_renderer_t *renderer)
+-{
+-  ply_list_t *heads;
+-  ply_list_node_t *node;
+-
+-  heads = ply_renderer_get_heads (renderer);
+-
+-  node = ply_list_get_first_node (heads);
+-  while (node != NULL)
+-    {
+-      ply_list_node_t *next_node;
+-      ply_renderer_head_t *head;
+-      ply_pixel_display_t *display;
+-
+-      head = ply_list_node_get_data (node);
+-      next_node = ply_list_get_next_node (heads, node);
+-
+-      display = ply_pixel_display_new (renderer, head);
+-
+-      ply_boot_splash_add_pixel_display (state->splash, display);
+-
+-      node = next_node;
+-    }
+-}
+-
+-int
+-main (int    argc,
+-      char **argv)
+-{
+-  int exit_code;
+-  test_state_t state;
+-  char *tty_name;
+-  const char *theme_path;
+-  ply_text_display_t *text_display;
+-  ply_renderer_t *renderer;
+-  ply_terminal_t *terminal;
+-  ply_keyboard_t *keyboard;
+-
+-  exit_code = 0;
+-
+-  state.loop = ply_event_loop_new ();
+-
+-  if (argc > 1)
+-    theme_path = argv[1];
+-  else
+-    theme_path = PLYMOUTH_THEME_PATH "/fade-in/fade-in.plymouth";
+-
+-  if (argc > 2)
+-    asprintf(&tty_name, "tty%s", argv[2]);
+-  else
+-    tty_name = strdup("tty0");
+-
+-  terminal = ply_terminal_new (tty_name);
+-
+-  if (!ply_terminal_open (terminal))
+-    {
+-      perror ("could not open tty");
+-      return errno;
+-    }
+-
+-  renderer = ply_renderer_new (NULL, terminal);
+-  free(tty_name);
+-
+-  if (!ply_renderer_open (renderer))
+-    {
+-      perror ("could not open renderer /dev/fb");
+-      ply_renderer_free (renderer);
+-      return errno;
+-    }
+-
+-  keyboard = ply_keyboard_new_for_renderer (renderer);
+-  ply_keyboard_add_escape_handler (keyboard,
+-                                   (ply_keyboard_escape_handler_t) on_quit, &state);
+-
+-  state.buffer = ply_buffer_new ();
+-  state.splash = ply_boot_splash_new (theme_path, PLYMOUTH_PLUGIN_PATH, state.buffer);
+-
+-  if (!ply_boot_splash_load (state.splash))
+-    {
+-      perror ("could not load splash screen");
+-      return errno;
+-    }
+-
+-  ply_boot_splash_set_keyboard (state.splash, keyboard);
+-  add_displays_to_splash_from_renderer (&state, renderer);
+-
+-  text_display = ply_text_display_new (terminal);
+-  ply_boot_splash_add_text_display (state.splash, text_display);
+-
+-  ply_boot_splash_attach_to_event_loop (state.splash, state.loop);
+-
+-  if (!ply_boot_splash_show (state.splash, PLY_BOOT_SPLASH_MODE_BOOT_UP))
+-    {
+-      perror ("could not show splash screen");
+-      return errno;
+-    }
+-
+-  ply_event_loop_watch_for_timeout (state.loop, 
+-                                    1.0,
+-                                   (ply_event_loop_timeout_handler_t)
+-                                   on_timeout,
+-                                   state.splash);
+-  exit_code = ply_event_loop_run (state.loop);
+-  ply_boot_splash_free (state.splash);
+-  ply_buffer_free (state.buffer);
+-
+-  return exit_code;
+-}
+-
+-#endif /* PLY_BOOT_SPLASH_ENABLE_TEST */
+ /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
+diff --git a/src/libply-splash-core/ply-boot-splash.h b/src/libply-splash-core/ply-boot-splash.h
+index a79e939..335039b 100644
+--- a/src/libply-splash-core/ply-boot-splash.h
++++ b/src/libply-splash-core/ply-boot-splash.h
+@@ -33,10 +33,12 @@
+ #include "ply-pixel-display.h"
+ #include "ply-text-display.h"
+ #include "ply-progress.h"
++#include "ply-seat.h"
+ 
+ #include "ply-boot-splash-plugin.h"
+ 
+ typedef struct _ply_boot_splash ply_boot_splash_t;
++typedef struct _ply_seat ply_seat_t;
+ 
+ typedef void (* ply_boot_splash_on_idle_handler_t) (void *user_data);
+ 
+@@ -48,17 +50,10 @@ ply_boot_splash_t *ply_boot_splash_new (const char   *  theme_path,
+ bool ply_boot_splash_load (ply_boot_splash_t *splash);
+ bool ply_boot_splash_load_built_in (ply_boot_splash_t *splash);
+ void ply_boot_splash_unload (ply_boot_splash_t *splash);
+-void ply_boot_splash_set_keyboard (ply_boot_splash_t *splash,
+-                                   ply_keyboard_t    *keyboard);
+-void ply_boot_splash_unset_keyboard (ply_boot_splash_t *splash);
+-void ply_boot_splash_add_pixel_display (ply_boot_splash_t   *splash,
+-                                        ply_pixel_display_t *display);
+-void ply_boot_splash_remove_pixel_display (ply_boot_splash_t   *splash,
+-                                           ply_pixel_display_t *display);
+-void ply_boot_splash_add_text_display (ply_boot_splash_t   *splash,
+-                                        ply_text_display_t *display);
+-void ply_boot_splash_remove_text_display (ply_boot_splash_t   *splash,
+-                                           ply_text_display_t *display);
++void ply_boot_splash_attach_to_seat (ply_boot_splash_t *splash,
++                                     ply_seat_t        *seat);
++void ply_boot_splash_detach_from_seat (ply_boot_splash_t *splash,
++                                       ply_seat_t        *seat);
+ void ply_boot_splash_free (ply_boot_splash_t *splash);
+ bool ply_boot_splash_show (ply_boot_splash_t *splash,
+                            ply_boot_splash_mode_t mode);
+diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
+new file mode 100644
+index 0000000..dbc203d
+--- /dev/null
++++ b/src/libply-splash-core/ply-device-manager.c
+@@ -0,0 +1,935 @@
++/* ply-device-manager.c - device manager
++ *
++ * Copyright (C) 2013 Red Hat, Inc.
++ *
++ * 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, 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-1307, USA.
++ */
++#include "config.h"
++#include "ply-device-manager.h"
++
++#include <assert.h>
++#include <fcntl.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <sys/inotify.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++
++#include <libudev.h>
++
++#include "ply-logger.h"
++#include "ply-event-loop.h"
++#include "ply-hashtable.h"
++#include "ply-list.h"
++#include "ply-utils.h"
++
++#define SUBSYSTEM_DRM "drm"
++#define SUBSYSTEM_FRAME_BUFFER "graphics"
++
++static void create_seat_for_terminal_and_renderer_type (ply_device_manager_t *manager,
++                                                        const char           *device_path,
++                                                        ply_terminal_t       *terminal,
++                                                        ply_renderer_type_t   renderer_type);
++struct _ply_device_manager
++{
++  ply_device_manager_flags_t  flags;
++  ply_event_loop_t           *loop;
++  ply_hashtable_t            *terminals;
++  ply_terminal_t             *local_console_terminal;
++  ply_seat_t                 *local_console_seat;
++  ply_list_t                 *seats;
++  struct udev                *udev_context;
++  struct udev_queue          *udev_queue;
++  int                         udev_queue_fd;
++  ply_fd_watch_t             *udev_queue_fd_watch;
++  struct udev_monitor        *udev_monitor;
++
++  ply_seat_added_handler_t    seat_added_handler;
++  ply_seat_removed_handler_t  seat_removed_handler;
++  void                       *seat_event_handler_data;
++};
++
++static void
++detach_from_event_loop (ply_device_manager_t *manager)
++{
++  assert (manager != NULL);
++
++  manager->loop = NULL;
++}
++
++static void
++attach_to_event_loop (ply_device_manager_t *manager,
++                      ply_event_loop_t     *loop)
++{
++  assert (manager != NULL);
++  assert (loop != NULL);
++  assert (manager->loop == NULL);
++
++  manager->loop = loop;
++
++  ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
++                                 detach_from_event_loop,
++                                 manager);
++}
++
++static bool
++device_is_for_local_console (ply_device_manager_t *manager,
++                             struct udev_device   *device)
++{
++  const char *device_path;
++  struct udev_device *bus_device;
++  char *bus_device_path;
++  const char *boot_vga;
++  bool for_local_console;
++
++  /* Look at the associated bus device to see if this card is the
++   * card the kernel is using for its console. */
++  device_path = udev_device_get_syspath (device);
++  asprintf (&bus_device_path, "%s/device", device_path);
++  bus_device = udev_device_new_from_syspath (manager->udev_context, bus_device_path);
++
++  boot_vga = udev_device_get_sysattr_value (bus_device, "boot_vga");
++  free (bus_device_path);
++
++  if (boot_vga != NULL && strcmp (boot_vga, "1") == 0)
++    for_local_console = true;
++  else
++    for_local_console = false;
++
++  return for_local_console;
++}
++
++static bool
++fb_device_has_drm_device (ply_device_manager_t *manager,
++                          struct udev_device   *fb_device)
++{
++  struct udev_enumerate *card_matches;
++  struct udev_list_entry *card_entry;
++  const char *id_path;
++  bool has_drm_device = false;
++
++  /* We want to see if the framebuffer is associated with a DRM-capable
++   * graphics card, if it is, we'll use the DRM device */
++  card_matches = udev_enumerate_new (manager->udev_context);
++  udev_enumerate_add_match_is_initialized(card_matches);
++  udev_enumerate_add_match_parent (card_matches, udev_device_get_parent (fb_device));
++  udev_enumerate_add_match_subsystem (card_matches, "drm");
++  id_path = udev_device_get_property_value (fb_device, "ID_PATH");
++  udev_enumerate_add_match_property (card_matches, "ID_PATH", id_path);
++
++  ply_trace ("trying to find associated drm node for fb device (path: %s)", id_path);
++
++  udev_enumerate_scan_devices (card_matches);
++
++  /* there should only ever be at most one match so we don't iterate through
++   * the list, but just look at the first entry */
++  card_entry = udev_enumerate_get_list_entry (card_matches);
++
++  if (card_entry != NULL)
++    {
++      struct udev_device *card_device = NULL;
++      const char *card_node;
++      const char *card_path;
++
++      card_path = udev_list_entry_get_name (card_entry);
++      card_device = udev_device_new_from_syspath (manager->udev_context, card_path);
++      card_node = udev_device_get_devnode (card_device);
++      if (card_node != NULL)
++        has_drm_device = true;
++      else
++        ply_trace ("no card node!");
++
++      udev_device_unref (card_device);
++    }
++  else
++    {
++      ply_trace ("no card entry!");
++    }
++
++  udev_enumerate_unref (card_matches);
++  return has_drm_device;
++}
++
++static void
++create_seat_for_udev_device (ply_device_manager_t *manager,
++                             struct udev_device   *device)
++{
++  bool for_local_console;
++  const char *device_path;
++  ply_terminal_t *terminal = NULL;
++
++  for_local_console = device_is_for_local_console (manager, device);
++
++  ply_trace ("device is for local console: %s", for_local_console? "yes" : "no");
++
++  if (for_local_console)
++    terminal = manager->local_console_terminal;
++
++  device_path = udev_device_get_devnode (device);
++
++  if (device_path != NULL)
++    {
++      const char *subsystem;
++      ply_renderer_type_t renderer_type = PLY_RENDERER_TYPE_NONE;
++
++      subsystem = udev_device_get_subsystem (device);
++      ply_trace ("device subsystem is %s", subsystem);
++
++      if (subsystem != NULL && strcmp (subsystem, SUBSYSTEM_DRM) == 0)
++        {
++          ply_trace ("found DRM device %s", device_path);
++          renderer_type = PLY_RENDERER_TYPE_DRM;
++        }
++      else if (strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0)
++        {
++          ply_trace ("found frame buffer device %s", device_path);
++          if (!fb_device_has_drm_device (manager, device))
++            {
++              renderer_type = PLY_RENDERER_TYPE_FRAME_BUFFER;
++            }
++          else
++            {
++              ply_trace ("ignoring, since there's a DRM device associated with it");
++            }
++        }
++
++      if (renderer_type != PLY_RENDERER_TYPE_NONE)
++        create_seat_for_terminal_and_renderer_type (manager,
++                                                    device_path,
++                                                    terminal,
++                                                    renderer_type);
++    }
++}
++
++static void
++free_seat_from_device_path (ply_device_manager_t *manager,
++                            const char           *device_path)
++{
++  ply_list_node_t *node;
++
++  node = ply_list_get_first_node (manager->seats);
++  while (node != NULL)
++    {
++      ply_seat_t *seat;
++      ply_renderer_t *renderer;
++      ply_list_node_t *next_node;
++      const char *renderer_device_path;
++
++      seat = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (manager->seats, node);
++      renderer = ply_seat_get_renderer (seat);
++
++      if (renderer != NULL)
++        {
++          renderer_device_path = ply_renderer_get_device_name (renderer);
++
++          if (renderer_device_path != NULL)
++            {
++              if (strcmp (device_path, renderer_device_path) == 0)
++                {
++                  ply_trace ("removing seat associated with %s", device_path);
++
++                  if (manager->seat_removed_handler != NULL)
++                    manager->seat_removed_handler (manager->seat_event_handler_data, seat);
++
++                  ply_seat_free (seat);
++                  ply_list_remove_node (manager->seats, node);
++                  break;
++                }
++            }
++        }
++
++      node = next_node;
++    }
++}
++
++static void
++free_seat_for_udev_device (ply_device_manager_t *manager,
++                           struct udev_device   *device)
++{
++  const char *device_path;
++
++  device_path = udev_device_get_devnode (device);
++
++  if (device_path != NULL)
++    free_seat_from_device_path (manager, device_path);
++}
++
++static bool
++create_seats_for_subsystem (ply_device_manager_t *manager,
++                            const char           *subsystem)
++{
++  struct udev_enumerate *matches;
++  struct udev_list_entry *entry;
++  bool found_device = false;
++
++  ply_trace ("creating seats for %s devices",
++             strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0?
++             "frame buffer":
++             subsystem);
++
++  matches = udev_enumerate_new (manager->udev_context);
++  udev_enumerate_add_match_subsystem (matches, subsystem);
++  udev_enumerate_scan_devices (matches);
++
++  udev_list_entry_foreach (entry, udev_enumerate_get_list_entry (matches))
++    {
++      struct udev_device *device = NULL;
++      const char *path;
++
++      path = udev_list_entry_get_name (entry);
++
++      if (path == NULL)
++        {
++          ply_trace ("path was null!");
++          continue;
++        }
++
++      ply_trace ("found device %s", path);
++
++      device = udev_device_new_from_syspath (manager->udev_context, path);
++
++      /* if device isn't fully initialized, we'll get an add event later
++       */
++      if (udev_device_get_is_initialized (device))
++        {
++          ply_trace ("device is initialized");
++
++          /* We only care about devices assigned to a (any) seat. Floating
++           * devices should be ignored.
++           */
++          if (udev_device_has_tag (device, "seat"))
++            {
++              const char *node;
++              node = udev_device_get_devnode (device);
++              if (node != NULL)
++                {
++                  ply_trace ("found node %s", node);
++                  found_device = true;
++                  create_seat_for_udev_device (manager, device);
++                }
++            }
++          else
++            {
++              ply_trace ("device doesn't have a seat tag");
++            }
++        }
++      else
++        {
++          ply_trace ("it's not initialized");
++        }
++
++      udev_device_unref (device);
++    }
++
++  udev_enumerate_unref (matches);
++
++  return found_device;
++}
++
++static void
++on_udev_event (ply_device_manager_t *manager)
++{
++  struct udev_device *device;
++  const char *action;
++
++  device = udev_monitor_receive_device (manager->udev_monitor);
++  if (device == NULL)
++    return;
++
++  action = udev_device_get_action (device);
++
++  ply_trace ("got %s event for device %s", action, udev_device_get_sysname (device));
++
++  if (action == NULL)
++    return;
++
++  if (strcmp (action, "add") == 0)
++    {
++      const char *subsystem;
++      bool coldplug_complete = manager->udev_queue_fd_watch == NULL;
++
++      subsystem = udev_device_get_subsystem (device);
++
++      if (strcmp (subsystem, SUBSYSTEM_DRM) == 0 ||
++          coldplug_complete)
++        {
++          create_seat_for_udev_device (manager, device);
++        }
++      else
++        {
++          ply_trace ("ignoring since we only handle subsystem %s devices after coldplug completes", subsystem);
++        }
++    }
++  else if (strcmp (action, "remove") == 0)
++    {
++      free_seat_for_udev_device (manager, device);
++    }
++
++  udev_device_unref (device);
++}
++
++static void
++watch_for_udev_events (ply_device_manager_t *manager)
++{
++  int fd;
++  assert (manager != NULL);
++  assert (manager->udev_monitor == NULL);
++
++  ply_trace ("watching for udev graphics device add and remove events");
++
++  manager->udev_monitor = udev_monitor_new_from_netlink (manager->udev_context, "udev");
++
++  udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_DRM, NULL);
++  udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_FRAME_BUFFER, NULL);
++  udev_monitor_filter_add_match_tag (manager->udev_monitor, "seat");
++  udev_monitor_enable_receiving (manager->udev_monitor);
++
++  fd = udev_monitor_get_fd (manager->udev_monitor);
++  ply_event_loop_watch_fd (manager->loop,
++                           fd,
++                           PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
++                           (ply_event_handler_t)
++                           on_udev_event,
++                           NULL,
++                           manager);
++}
++
++static void
++free_seats (ply_device_manager_t *manager)
++{
++  ply_list_node_t *node;
++
++  ply_trace ("removing seats");
++  node = ply_list_get_first_node (manager->seats);
++  while (node != NULL)
++    {
++      ply_seat_t *seat;
++      ply_list_node_t *next_node;
++
++      seat = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (manager->seats, node);
++
++      if (manager->seat_removed_handler != NULL)
++        manager->seat_removed_handler (manager->seat_event_handler_data, seat);
++
++      ply_seat_free (seat);
++      ply_list_remove_node (manager->seats, node);
++
++      node = next_node;
++    }
++}
++
++static void
++free_terminal (char                 *device,
++               ply_terminal_t       *terminal,
++               ply_device_manager_t *manager)
++{
++  ply_hashtable_remove (manager->terminals, device);
++
++  ply_terminal_close (terminal);
++  ply_terminal_free (terminal);
++}
++
++static void
++free_terminals (ply_device_manager_t *manager)
++{
++  ply_hashtable_foreach (manager->terminals,
++                         (ply_hashtable_foreach_func_t *)
++                         free_terminal,
++                         manager);
++}
++
++static ply_terminal_t *
++get_terminal (ply_device_manager_t *manager,
++              const char           *device_name)
++{
++  char *full_name = NULL;
++  ply_terminal_t *terminal;
++
++  if (strncmp (device_name, "/dev/", strlen ("/dev/")) == 0)
++    full_name = strdup (device_name);
++  else
++    asprintf (&full_name, "/dev/%s", device_name);
++
++  if (strcmp (full_name, "/dev/tty0") == 0 ||
++      strcmp (full_name, "/dev/tty") == 0 ||
++      strcmp (full_name, ply_terminal_get_name (manager->local_console_terminal)) == 0)
++    {
++      terminal = manager->local_console_terminal;
++      goto done;
++    }
++
++  terminal = ply_hashtable_lookup (manager->terminals, full_name);
++
++  if (terminal == NULL)
++    {
++      terminal = ply_terminal_new (full_name);
++
++      ply_hashtable_insert (manager->terminals,
++                            (void *) ply_terminal_get_name (terminal),
++                            terminal);
++    }
++
++done:
++  free (full_name);
++  return terminal;
++}
++
++ply_device_manager_t *
++ply_device_manager_new (const char                 *default_tty,
++                        ply_device_manager_flags_t  flags)
++{
++  ply_device_manager_t *manager;
++
++  manager = calloc (1, sizeof (ply_device_manager_t));
++  manager->loop = NULL;
++  manager->terminals = ply_hashtable_new (ply_hashtable_string_hash, ply_hashtable_string_compare);
++  manager->local_console_terminal = ply_terminal_new (default_tty);
++  ply_hashtable_insert (manager->terminals,
++                        (void *) ply_terminal_get_name (manager->local_console_terminal),
++                        manager->local_console_terminal);
++  manager->seats = ply_list_new ();
++  manager->flags = flags;
++
++  if (!(flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV))
++    manager->udev_context = udev_new ();
++
++  attach_to_event_loop (manager, ply_event_loop_get_default ());
++
++  return manager;
++}
++
++void
++ply_device_manager_free (ply_device_manager_t *manager)
++{
++  ply_trace ("freeing device manager");
++
++  if (manager == NULL)
++    return;
++
++  ply_event_loop_stop_watching_for_exit (manager->loop,
++                                         (ply_event_loop_exit_handler_t)
++                                         detach_from_event_loop,
++                                         manager);
++  free_seats (manager);
++  ply_list_free (manager->seats);
++
++  free_terminals (manager);
++  ply_hashtable_free (manager->terminals);
++
++  if (manager->udev_monitor != NULL)
++    udev_monitor_unref (manager->udev_monitor);
++
++  if (manager->udev_context != NULL)
++    udev_unref (manager->udev_context);
++
++  free (manager);
++}
++
++static bool
++add_consoles_from_file (ply_device_manager_t *manager,
++                        const char           *path)
++{
++  int fd;
++  char contents[512] = "";
++  ssize_t contents_length;
++  bool has_serial_consoles;
++  const char *remaining_file_contents;
++
++  ply_trace ("opening %s", path);
++  fd = open (path, O_RDONLY);
++
++  if (fd < 0)
++    {
++      ply_trace ("couldn't open it: %m");
++      return false;
++    }
++
++  ply_trace ("reading file");
++  contents_length = read (fd, contents, sizeof (contents) - 1);
++
++  if (contents_length <= 0)
++    {
++      ply_trace ("couldn't read it: %m");
++      close (fd);
++      return false;
++    }
++  close (fd);
++
++  remaining_file_contents = contents;
++  has_serial_consoles = false;
++
++  while (remaining_file_contents < contents + contents_length)
++    {
++      char *console;
++      size_t console_length;
++      const char *console_device;
++      ply_terminal_t *terminal;
++
++      /* Advance past any leading whitespace */
++      remaining_file_contents += strspn (remaining_file_contents, " \n\t\v");
++
++      if (*remaining_file_contents == '\0')
++        {
++          /* There's nothing left after the whitespace, we're done */
++          break;
++        }
++
++      /* Find trailing whitespace and NUL terminate.  If strcspn
++       * doesn't find whitespace, it gives us the length of the string
++       * until the next NUL byte, which we'll just overwrite with
++       * another NUL byte anyway. */
++      console_length = strcspn (remaining_file_contents, " \n\t\v");
++      console = strndup (remaining_file_contents, console_length);
++
++      terminal = get_terminal (manager, console);
++      console_device = ply_terminal_get_name (terminal);
++
++      free (console);
++
++      ply_trace ("console %s found!", console_device);
++
++      if (terminal != manager->local_console_terminal)
++        has_serial_consoles = true;
++
++      /* Move past the parsed console string, and the whitespace we
++       * may have found above.  If we found a NUL above and not whitespace,
++       * then we're going to jump past the end of the buffer and the loop
++       * will terminate
++       */
++      remaining_file_contents += console_length + 1;
++    }
++
++  return has_serial_consoles;
++}
++
++static void
++create_seat_for_terminal_and_renderer_type (ply_device_manager_t *manager,
++                                            const char           *device_path,
++                                            ply_terminal_t       *terminal,
++                                            ply_renderer_type_t   renderer_type)
++{
++  ply_seat_t *seat;
++  bool is_local_terminal = false;
++
++  if (terminal != NULL && manager->local_console_terminal == terminal)
++    is_local_terminal = true;
++
++  if (is_local_terminal && manager->local_console_seat != NULL)
++    {
++      ply_trace ("trying to create seat for local console when one already exists");
++      return;
++    }
++
++  ply_trace ("creating seat for %s (renderer type: %u) (terminal: %s)",
++             device_path? : "", renderer_type, terminal? ply_terminal_get_name (terminal): "none");
++  seat = ply_seat_new (terminal);
++
++  if (!ply_seat_open (seat, renderer_type, device_path))
++    {
++      ply_trace ("could not create seat");
++      ply_seat_free (seat);
++      return;
++    }
++
++  ply_list_append_data (manager->seats, seat);
++
++  if (is_local_terminal)
++    manager->local_console_seat = seat;
++
++  if (manager->seat_added_handler != NULL)
++    manager->seat_added_handler (manager->seat_event_handler_data, seat);
++}
++
++static void
++create_seat_for_terminal (const char           *device_path,
++                          ply_terminal_t       *terminal,
++                          ply_device_manager_t *manager)
++{
++  create_seat_for_terminal_and_renderer_type (manager,
++                                              device_path,
++                                              terminal,
++                                              PLY_RENDERER_TYPE_NONE);
++}
++static bool
++create_seats_from_terminals (ply_device_manager_t *manager)
++{
++  bool has_serial_consoles;
++
++  ply_trace ("checking for consoles");
++
++  if (manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES)
++    {
++      has_serial_consoles = false;
++      ply_trace ("ignoring all consoles but default console because explicitly told to.");
++    }
++  else
++    {
++      has_serial_consoles = add_consoles_from_file (manager, "/sys/class/tty/console/active");
++    }
++
++  if (has_serial_consoles)
++    {
++      ply_trace ("serial consoles detected, managing them with details forced");
++      ply_hashtable_foreach (manager->terminals,
++                             (ply_hashtable_foreach_func_t *)
++                             create_seat_for_terminal,
++                             manager);
++      return true;
++    }
++
++  return false;
++}
++
++static void
++create_seats_from_udev (ply_device_manager_t *manager)
++{
++  bool found_drm_device, found_fb_device;
++
++  ply_trace ("Looking for devices from udev");
++
++  found_drm_device = create_seats_for_subsystem (manager, SUBSYSTEM_DRM);
++  found_fb_device = create_seats_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER);
++
++  if (found_drm_device || found_fb_device)
++    return;
++
++  ply_trace ("Creating non-graphical seat, since there's no suitable graphics hardware");
++  create_seat_for_terminal_and_renderer_type (manager,
++                                              ply_terminal_get_name (manager->local_console_terminal),
++                                              manager->local_console_terminal,
++                                              PLY_RENDERER_TYPE_NONE);
++}
++
++static void
++create_fallback_seat (ply_device_manager_t *manager)
++{
++  create_seat_for_terminal_and_renderer_type (manager,
++                                              ply_terminal_get_name (manager->local_console_terminal),
++                                              manager->local_console_terminal,
++                                              PLY_RENDERER_TYPE_AUTO);
++}
++
++static void
++on_udev_queue_changed (ply_device_manager_t *manager)
++{
++
++  if (!udev_queue_get_queue_is_empty (manager->udev_queue))
++    return;
++
++  ply_trace ("udev coldplug complete");
++  ply_event_loop_stop_watching_fd (manager->loop, manager->udev_queue_fd_watch);
++  manager->udev_queue_fd_watch = NULL;
++  udev_queue_unref (manager->udev_queue);
++
++  close (manager->udev_queue_fd);
++  manager->udev_queue_fd = -1;
++
++  manager->udev_queue = NULL;
++
++  create_seats_from_udev (manager);
++}
++
++static void
++watch_for_coldplug_completion (ply_device_manager_t *manager)
++{
++  int fd;
++  int result;
++
++  manager->udev_queue = udev_queue_new (manager->udev_context);
++
++  if (udev_queue_get_queue_is_empty (manager->udev_queue))
++    {
++      ply_trace ("udev coldplug completed already ");
++      create_seats_from_udev (manager);
++      return;
++    }
++
++  fd = inotify_init1 (IN_CLOEXEC);
++  result = inotify_add_watch (fd, "/run/udev", IN_MOVED_TO);
++
++  if (result < 0)
++    {
++      ply_trace ("could not watch for udev to show up: %m");
++      close (fd);
++
++      create_fallback_seat (manager);
++      return;
++    }
++
++  manager->udev_queue_fd = fd;
++
++  manager->udev_queue_fd_watch = ply_event_loop_watch_fd (manager->loop,
++                                                          fd,
++                                                          PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
++                                                          (ply_event_handler_t)
++                                                          on_udev_queue_changed,
++                                                          NULL,
++                                                          manager);
++
++}
++
++void
++ply_device_manager_watch_seats (ply_device_manager_t       *manager,
++                                ply_seat_added_handler_t    seat_added_handler,
++                                ply_seat_removed_handler_t  seat_removed_handler,
++                                void                       *data)
++{
++  bool done_with_initial_seat_setup;
++
++  manager->seat_added_handler = seat_added_handler;
++  manager->seat_removed_handler = seat_removed_handler;
++  manager->seat_event_handler_data = data;
++
++  /* Try to create seats for each serial device right away, if possible
++   */
++  done_with_initial_seat_setup = create_seats_from_terminals (manager);
++
++  if (done_with_initial_seat_setup)
++    return;
++
++  if ((manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV))
++    {
++      ply_trace ("udev support disabled, creating fallback seat");
++      create_fallback_seat (manager);
++      return;
++    }
++
++  watch_for_udev_events (manager);
++  watch_for_coldplug_completion (manager);
++}
++
++bool
++ply_device_manager_has_open_seats (ply_device_manager_t *manager)
++{
++  ply_list_node_t *node;
++
++  node = ply_list_get_first_node (manager->seats);
++  while (node != NULL)
++    {
++      ply_seat_t *seat;
++      ply_list_node_t *next_node;
++
++      seat = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (manager->seats, node);
++
++      if (ply_seat_is_open (seat))
++        return true;
++
++      node = next_node;
++    }
++
++  return false;
++}
++
++ply_list_t *
++ply_device_manager_get_seats (ply_device_manager_t *manager)
++{
++  return manager->seats;
++}
++
++ply_terminal_t *
++ply_device_manager_get_default_terminal (ply_device_manager_t *manager)
++{
++  return manager->local_console_terminal;
++}
++
++void
++ply_device_manager_activate_renderers (ply_device_manager_t *manager)
++{
++  ply_list_node_t *node;
++
++  ply_trace ("activating renderers");
++  node = ply_list_get_first_node (manager->seats);
++  while (node != NULL)
++    {
++      ply_seat_t *seat;
++      ply_list_node_t *next_node;
++
++      seat = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (manager->seats, node);
++
++      ply_seat_activate_renderer (seat);
++
++      node = next_node;
++    }
++}
++
++void
++ply_device_manager_deactivate_renderers (ply_device_manager_t *manager)
++{
++  ply_list_node_t *node;
++
++  ply_trace ("deactivating renderers");
++  node = ply_list_get_first_node (manager->seats);
++  while (node != NULL)
++    {
++      ply_seat_t *seat;
++      ply_list_node_t *next_node;
++
++      seat = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (manager->seats, node);
++
++      ply_seat_deactivate_renderer (seat);
++
++      node = next_node;
++    }
++}
++
++void
++ply_device_manager_activate_keyboards (ply_device_manager_t *manager)
++{
++  ply_list_node_t *node;
++
++  ply_trace ("activating keyboards");
++  node = ply_list_get_first_node (manager->seats);
++  while (node != NULL)
++    {
++      ply_seat_t *seat;
++      ply_list_node_t *next_node;
++
++      seat = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (manager->seats, node);
++
++      ply_seat_activate_keyboard (seat);
++
++      node = next_node;
++    }
++}
++
++void
++ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager)
++{
++  ply_list_node_t *node;
++
++  ply_trace ("deactivating keyboards");
++  node = ply_list_get_first_node (manager->seats);
++  while (node != NULL)
++    {
++      ply_seat_t *seat;
++      ply_list_node_t *next_node;
++
++      seat = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (manager->seats, node);
++
++      ply_seat_deactivate_keyboard (seat);
++
++      node = next_node;
++    }
++}
+diff --git a/src/libply-splash-core/ply-device-manager.h b/src/libply-splash-core/ply-device-manager.h
+new file mode 100644
+index 0000000..d9c58e8
+--- /dev/null
++++ b/src/libply-splash-core/ply-device-manager.h
+@@ -0,0 +1,56 @@
++/* ply-device-manager.h - udev monitor
++ *
++ * Copyright (C) 2013 Red Hat, Inc.
++ *
++ * 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, 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-1307, USA.
++ */
++#ifndef PLY_DEVICE_MANAGER_H
++#define PLY_DEVICE_MANAGER_H
++
++#include <stdbool.h>
++#include "ply-seat.h"
++
++typedef enum
++{
++  PLY_DEVICE_MANAGER_FLAGS_NONE                   = 0,
++  PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES = 1 << 0,
++  PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV            = 1 << 1
++} ply_device_manager_flags_t;
++
++typedef struct _ply_device_manager ply_device_manager_t;
++typedef void (* ply_seat_added_handler_t) (void *, ply_seat_t *);
++typedef void (* ply_seat_removed_handler_t) (void *, ply_seat_t *);
++
++#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
++ply_device_manager_t *ply_device_manager_new (const char                 *default_tty,
++                                              ply_device_manager_flags_t  flags);
++void ply_device_manager_watch_seats (ply_device_manager_t *manager,
++                                     ply_seat_added_handler_t seat_added_handler,
++                                     ply_seat_removed_handler_t seat_removed_handler,
++                                     void *data);
++bool ply_device_manager_has_open_seats (ply_device_manager_t *manager);
++ply_list_t *ply_device_manager_get_seats (ply_device_manager_t *manager);
++void ply_device_manager_free (ply_device_manager_t *manager);
++void ply_device_manager_activate_keyboards (ply_device_manager_t *manager);
++void ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager);
++void ply_device_manager_activate_renderers (ply_device_manager_t *manager);
++void ply_device_manager_deactivate_renderers (ply_device_manager_t *manager);
++ply_terminal_t *ply_device_manager_get_default_terminal (ply_device_manager_t *manager);
++
++#endif
++
++#endif
++/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
+diff --git a/src/libply-splash-core/ply-pixel-buffer.c b/src/libply-splash-core/ply-pixel-buffer.c
+index a612990..a860b7f 100644
+--- a/src/libply-splash-core/ply-pixel-buffer.c
++++ b/src/libply-splash-core/ply-pixel-buffer.c
+@@ -848,5 +848,35 @@ ply_pixel_buffer_rotate (ply_pixel_buffer_t *old_buffer,
+   return buffer;
+ }
+ 
++ply_pixel_buffer_t *
++ply_pixel_buffer_tile (ply_pixel_buffer_t *old_buffer,
++                       long                width,
++                       long                height)
++{
++  long x, y;
++  long old_x, old_y;
++  long old_width, old_height;
++  uint32_t *bytes, *old_bytes;
++  ply_pixel_buffer_t *buffer;
++
++  buffer = ply_pixel_buffer_new (width, height);
++
++  old_bytes = ply_pixel_buffer_get_argb32_data (old_buffer);
++  bytes = ply_pixel_buffer_get_argb32_data (buffer);
++
++  old_width = old_buffer->area.width;
++  old_height = old_buffer->area.height;
++
++  for (y = 0; y < height; y++)
++    {
++      old_y = y % old_height;
++      for (x = 0; x < width; x++)
++        {
++          old_x = x % old_width;
++          bytes[x + y * width] = old_bytes[old_x + old_y * old_width];
++        }
++    }
++  return buffer;
++}
+ 
+ /* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
+diff --git a/src/libply-splash-core/ply-pixel-buffer.h b/src/libply-splash-core/ply-pixel-buffer.h
+index 47cdd52..e0dffda 100644
+--- a/src/libply-splash-core/ply-pixel-buffer.h
++++ b/src/libply-splash-core/ply-pixel-buffer.h
+@@ -124,6 +124,10 @@ ply_pixel_buffer_t *ply_pixel_buffer_rotate (ply_pixel_buffer_t *old_buffer,
+                                              long                center_y,
+                                              double              theta_offset);
+ 
++ply_pixel_buffer_t *ply_pixel_buffer_tile (ply_pixel_buffer_t *old_buffer,
++                                           long                width,
++                                           long                height);
++
+ #endif
+ 
+ #endif /* PLY_PIXEL_BUFFER_H */
+diff --git a/src/libply-splash-core/ply-renderer.c b/src/libply-splash-core/ply-renderer.c
+index 3559e01..04a99ce 100644
+--- a/src/libply-splash-core/ply-renderer.c
++++ b/src/libply-splash-core/ply-renderer.c
+@@ -49,7 +49,7 @@ struct _ply_renderer
+   const ply_renderer_plugin_interface_t *plugin_interface;
+   ply_renderer_backend_t *backend;
+ 
+-  char *plugin_path;
++  ply_renderer_type_t type;
+   char *device_name;
+   ply_terminal_t *terminal;
+ 
+@@ -63,16 +63,15 @@ typedef const ply_renderer_plugin_interface_t *
+ static void ply_renderer_unload_plugin (ply_renderer_t *renderer);
+ 
+ ply_renderer_t *
+-ply_renderer_new (const char     *plugin_path,
+-                  const char     *device_name,
+-                  ply_terminal_t *terminal)
++ply_renderer_new (ply_renderer_type_t  renderer_type,
++                  const char          *device_name,
++                  ply_terminal_t      *terminal)
+ {
+   ply_renderer_t *renderer;
+ 
+   renderer = calloc (1, sizeof (struct _ply_renderer));
+ 
+-  if (plugin_path != NULL)
+-    renderer->plugin_path = strdup (plugin_path);
++  renderer->type = renderer_type;
+ 
+   if (device_name != NULL)
+     renderer->device_name = strdup (device_name);
+@@ -95,10 +94,15 @@ ply_renderer_free (ply_renderer_t *renderer)
+     }
+ 
+   free (renderer->device_name);
+-  free (renderer->plugin_path);
+   free (renderer);
+ }
+ 
++const char *
++ply_renderer_get_device_name (ply_renderer_t *renderer)
++{
++  return renderer->device_name;
++}
++
+ static bool
+ ply_renderer_load_plugin (ply_renderer_t *renderer,
+                           const char     *module_path)
+@@ -258,29 +262,28 @@ ply_renderer_open (ply_renderer_t *renderer)
+ {
+   int i;
+ 
+-  /* FIXME: at some point we may want to make this
+-   * part more dynamic (so you don't have to edit this
+-   * list to add a new renderer)
+-   */
+-  const char *known_plugins[] =
++  struct
+     {
+-      PLYMOUTH_PLUGIN_PATH "renderers/x11.so",
+-      PLYMOUTH_PLUGIN_PATH "renderers/drm.so",
+-      PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so",
+-      NULL
++      ply_renderer_type_t  type;
++      const char          *path;
++    } known_plugins[] =
++    {
++      { PLY_RENDERER_TYPE_X11, PLYMOUTH_PLUGIN_PATH "renderers/x11.so" },
++      { PLY_RENDERER_TYPE_DRM, PLYMOUTH_PLUGIN_PATH "renderers/drm.so" },
++      { PLY_RENDERER_TYPE_FRAME_BUFFER, PLYMOUTH_PLUGIN_PATH "renderers/frame-buffer.so" },
++      { PLY_RENDERER_TYPE_NONE, NULL }
+     };
+ 
+-  if (renderer->plugin_path != NULL)
++  for (i = 0; known_plugins[i].type != PLY_RENDERER_TYPE_NONE; i++)
+     {
+-      return ply_renderer_open_plugin (renderer, renderer->plugin_path);
++      if (renderer->type == known_plugins[i].type ||
++          renderer->type == PLY_RENDERER_TYPE_AUTO)
++        {
++          if (ply_renderer_open_plugin (renderer, known_plugins[i].path))
++            return true;
++        }
+     }
+ 
+-  for (i = 0; known_plugins[i] != NULL; i++)
+-    {
+-      if (ply_renderer_open_plugin (renderer, known_plugins[i]))
+-        return true;
+-  }
+-
+   ply_trace ("could not find suitable rendering plugin");
+   return false;
+ }
+diff --git a/src/libply-splash-core/ply-renderer.h b/src/libply-splash-core/ply-renderer.h
+index 4b3bd1a..3d48341 100644
+--- a/src/libply-splash-core/ply-renderer.h
++++ b/src/libply-splash-core/ply-renderer.h
+@@ -35,12 +35,21 @@ typedef struct _ply_renderer ply_renderer_t;
+ typedef struct _ply_renderer_head ply_renderer_head_t;
+ typedef struct _ply_renderer_input_source ply_renderer_input_source_t;
+ 
++typedef enum
++{
++  PLY_RENDERER_TYPE_NONE = -1,
++  PLY_RENDERER_TYPE_AUTO,
++  PLY_RENDERER_TYPE_DRM,
++  PLY_RENDERER_TYPE_FRAME_BUFFER,
++  PLY_RENDERER_TYPE_X11
++} ply_renderer_type_t;
++
+ typedef void (* ply_renderer_input_source_handler_t) (void                        *user_data,
+                                                       ply_buffer_t                *key_buffer,
+                                                       ply_renderer_input_source_t *input_source);
+ 
+ #ifndef PLY_HIDE_FUNCTION_DECLARATIONS
+-ply_renderer_t *ply_renderer_new (const char     *plugin_path,
++ply_renderer_t *ply_renderer_new (ply_renderer_type_t renderer_type,
+                                   const char     *device_name,
+                                   ply_terminal_t *terminal);
+ void ply_renderer_free (ply_renderer_t *renderer);
+@@ -48,6 +57,7 @@ bool ply_renderer_open (ply_renderer_t *renderer);
+ void ply_renderer_close (ply_renderer_t *renderer);
+ void ply_renderer_activate (ply_renderer_t *renderer);
+ void ply_renderer_deactivate (ply_renderer_t *renderer);
++const char *ply_renderer_get_device_name (ply_renderer_t *renderer);
+ ply_list_t *ply_renderer_get_heads (ply_renderer_t *renderer);
+ ply_pixel_buffer_t *ply_renderer_get_buffer_for_head (ply_renderer_t      *renderer,
+                                                       ply_renderer_head_t *head);
+diff --git a/src/libply-splash-core/ply-seat.c b/src/libply-splash-core/ply-seat.c
+new file mode 100644
+index 0000000..2ac8bf7
+--- /dev/null
++++ b/src/libply-splash-core/ply-seat.c
+@@ -0,0 +1,387 @@
++/* ply-seat.c - APIs for encapsulating a keyboard and one or more displays
++ *
++ * Copyright (C) 2013 Red Hat, Inc.
++ *
++ * 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, 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-1307, USA.
++ *
++ * Written by: Ray Strode <rstrode at redhat.com>
++ */
++#include "config.h"
++#include "ply-seat.h"
++
++#include <assert.h>
++#include <errno.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++#include "ply-boot-splash.h"
++#include "ply-event-loop.h"
++#include "ply-keyboard.h"
++#include "ply-pixel-display.h"
++#include "ply-text-display.h"
++#include "ply-list.h"
++#include "ply-logger.h"
++#include "ply-utils.h"
++
++struct _ply_seat
++{
++  ply_event_loop_t *loop;
++
++  ply_boot_splash_t *splash;
++  ply_terminal_t *terminal;
++  ply_renderer_t *renderer;
++  ply_keyboard_t *keyboard;
++  ply_list_t *text_displays;
++  ply_list_t *pixel_displays;
++
++  uint32_t renderer_active : 1;
++  uint32_t keyboard_active : 1;
++};
++
++ply_seat_t *
++ply_seat_new (ply_terminal_t *terminal)
++{
++  ply_seat_t *seat;
++
++  seat = calloc (1, sizeof (ply_seat_t));
++
++  seat->loop = ply_event_loop_get_default ();
++  seat->terminal = terminal;
++  seat->text_displays = ply_list_new ();
++  seat->pixel_displays = ply_list_new ();
++
++  return seat;
++}
++
++static void
++add_pixel_displays (ply_seat_t *seat)
++{
++  ply_list_t *heads;
++  ply_list_node_t *node;
++
++  heads = ply_renderer_get_heads (seat->renderer);
++
++  ply_trace ("Adding displays for %d heads",
++             ply_list_get_length (heads));
++
++  node = ply_list_get_first_node (heads);
++  while (node != NULL)
++    {
++      ply_list_node_t *next_node;
++      ply_renderer_head_t *head;
++      ply_pixel_display_t *display;
++
++      head = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (heads, node);
++
++      display = ply_pixel_display_new (seat->renderer, head);
++
++      ply_list_append_data (seat->pixel_displays, display);
++
++      node = next_node;
++    }
++}
++
++static void
++add_text_displays (ply_seat_t *seat)
++{
++  ply_text_display_t *display;
++
++  if (!ply_terminal_is_open (seat->terminal))
++    {
++      if (!ply_terminal_open (seat->terminal))
++        {
++          ply_trace ("could not add terminal %s: %m",
++                     ply_terminal_get_name (seat->terminal));
++          return;
++        }
++    }
++
++  ply_trace ("adding text display for terminal %s",
++             ply_terminal_get_name (seat->terminal));
++
++  display = ply_text_display_new (seat->terminal);
++  ply_list_append_data (seat->text_displays, display);
++}
++
++bool
++ply_seat_open (ply_seat_t          *seat,
++               ply_renderer_type_t  renderer_type,
++               const char          *device)
++{
++  if (renderer_type != PLY_RENDERER_TYPE_NONE)
++    {
++      ply_renderer_t *renderer;
++
++      renderer = ply_renderer_new (renderer_type, device, seat->terminal);
++
++      if (!ply_renderer_open (renderer))
++        {
++          ply_trace ("could not open renderer for %s", device);
++          ply_renderer_free (renderer);
++
++          seat->renderer = NULL;
++          seat->renderer_active = false;
++
++          if (renderer_type != PLY_RENDERER_TYPE_AUTO)
++            return false;
++        }
++      else
++        {
++          seat->renderer = renderer;
++          seat->renderer_active = true;
++        }
++    }
++
++  if (seat->renderer != NULL)
++    {
++      seat->keyboard = ply_keyboard_new_for_renderer (seat->renderer);
++      add_pixel_displays (seat);
++
++    }
++  else
++    {
++      seat->keyboard = ply_keyboard_new_for_terminal (seat->terminal);
++    }
++  add_text_displays (seat);
++
++  ply_keyboard_watch_for_input (seat->keyboard);
++  seat->keyboard_active = true;
++
++  return true;
++}
++
++bool
++ply_seat_is_open (ply_seat_t *seat)
++{
++  return ply_list_get_length (seat->pixel_displays) > 0 ||
++         ply_list_get_length (seat->text_displays) > 0;
++}
++
++void
++ply_seat_deactivate_keyboard (ply_seat_t *seat)
++{
++  if (!seat->keyboard_active)
++    return;
++
++  seat->keyboard_active = false;
++
++  if (seat->keyboard == NULL)
++    return;
++
++  ply_trace ("deactivating keybord");
++  ply_keyboard_stop_watching_for_input (seat->keyboard);
++}
++
++void
++ply_seat_deactivate_renderer (ply_seat_t *seat)
++{
++  if (!seat->renderer_active)
++    return;
++
++  seat->renderer_active = false;
++
++  if (seat->renderer == NULL)
++    return;
++
++  ply_trace ("deactivating renderer");
++  ply_renderer_deactivate (seat->renderer);
++}
++
++void
++ply_seat_activate_keyboard (ply_seat_t *seat)
++{
++  if (seat->keyboard_active)
++    return;
++
++  if (seat->keyboard == NULL)
++    return;
++
++  ply_trace ("activating keyboard");
++  ply_keyboard_watch_for_input (seat->keyboard);
++
++  seat->keyboard_active = true;
++}
++
++void
++ply_seat_activate_renderer (ply_seat_t *seat)
++{
++  if (seat->renderer_active)
++    return;
++
++  if (seat->renderer == NULL)
++    return;
++
++  ply_trace ("activating renderer");
++  ply_renderer_activate (seat->renderer);
++
++  seat->renderer_active = true;
++}
++
++void
++ply_seat_refresh_displays (ply_seat_t *seat)
++{
++  ply_list_node_t *node;
++
++  node = ply_list_get_first_node (seat->pixel_displays);
++  while (node != NULL)
++    {
++      ply_pixel_display_t *display;
++      ply_list_node_t *next_node;
++      unsigned long width, height;
++
++      display = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (seat->pixel_displays, node);
++
++      width = ply_pixel_display_get_width (display);
++      height = ply_pixel_display_get_height (display);
++
++      ply_pixel_display_draw_area (display, 0, 0, width, height);
++      node = next_node;
++    }
++
++  node = ply_list_get_first_node (seat->text_displays);
++  while (node != NULL)
++    {
++      ply_text_display_t *display;
++      ply_list_node_t *next_node;
++      int number_of_columns, number_of_rows;
++
++      display = ply_list_node_get_data (node);
++      next_node = ply_list_get_next_node (seat->text_displays, node);
++
++      number_of_columns = ply_text_display_get_number_of_columns (display);
++      number_of_rows = ply_text_display_get_number_of_rows (display);
++
++      ply_text_display_draw_area (display, 0, 0,
++                                  number_of_columns,
++                                  number_of_rows);
++      node = next_node;
++    }
++}
++
++void
++ply_seat_close (ply_seat_t *seat)
++{
++  if (seat->renderer == NULL)
++    return;
++
++  ply_trace ("destroying renderer");
++  ply_renderer_close (seat->renderer);
++  ply_renderer_free (seat->renderer);
++  seat->renderer = NULL;
++}
++
++void
++ply_seat_set_splash (ply_seat_t        *seat,
++                     ply_boot_splash_t *splash)
++{
++  if (seat->splash == splash)
++    return;
++
++  if (seat->splash != NULL)
++    ply_boot_splash_detach_from_seat (splash, seat);
++
++  if (splash != NULL)
++    ply_boot_splash_attach_to_seat (splash, seat);
++
++  seat->splash = splash;
++}
++
++static void
++free_pixel_displays (ply_seat_t *seat)
++{
++  ply_list_node_t *node;
++
++  ply_trace ("freeing %d pixel displays", ply_list_get_length (seat->pixel_displays));
++  node = ply_list_get_first_node (seat->pixel_displays);
++  while (node != NULL)
++    {
++      ply_list_node_t *next_node;
++      ply_pixel_display_t *display;
++
++      next_node = ply_list_get_next_node (seat->pixel_displays, node);
++      display = ply_list_node_get_data (node);
++      ply_pixel_display_free (display);
++
++      ply_list_remove_node (seat->pixel_displays, node);
++
++      node = next_node;
++    }
++}
++
++static void
++free_text_displays (ply_seat_t *seat)
++{
++  ply_list_node_t *node;
++
++  ply_trace ("freeing %d text displays", ply_list_get_length (seat->text_displays));
++  node = ply_list_get_first_node (seat->text_displays);
++  while (node != NULL)
++    {
++      ply_list_node_t *next_node;
++      ply_text_display_t *display;
++
++      next_node = ply_list_get_next_node (seat->text_displays, node);
++      display = ply_list_node_get_data (node);
++      ply_text_display_free (display);
++
++      ply_list_remove_node (seat->text_displays, node);
++
++      node = next_node;
++    }
++}
++
++void
++ply_seat_free (ply_seat_t *seat)
++{
++  if (seat == NULL)
++    return;
++
++  free_pixel_displays (seat);
++  free_text_displays (seat);
++  ply_keyboard_free (seat->keyboard);
++
++  free (seat);
++}
++
++ply_list_t *
++ply_seat_get_pixel_displays (ply_seat_t *seat)
++{
++  return seat->pixel_displays;
++}
++
++ply_list_t *
++ply_seat_get_text_displays (ply_seat_t *seat)
++{
++  return seat->text_displays;
++}
++
++ply_keyboard_t *
++ply_seat_get_keyboard (ply_seat_t *seat)
++{
++  return seat->keyboard;
++}
++
++ply_renderer_t *
++ply_seat_get_renderer (ply_seat_t *seat)
++{
++  return seat->renderer;
++}
++
++/* vim: set ts=4 sw=4 et ai ci cino={.5s,^-2,+.5s,t0,g0,e-2,n-2,p2s,(0,=.5s,:.5s */
+diff --git a/src/libply-splash-core/ply-seat.h b/src/libply-splash-core/ply-seat.h
+new file mode 100644
+index 0000000..d5d3397
+--- /dev/null
++++ b/src/libply-splash-core/ply-seat.h
+@@ -0,0 +1,66 @@
++/* ply-seat.h - APIs for encapsulating a keyboard and one or more displays
++ *
++ * Copyright (C) 2013 Red Hat, Inc.
++ *
++ * 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, 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-1307, USA.
++ *
++ * Written By: Ray Strode <rstrode at redhat.com>
++ */
++#ifndef PLY_SEAT_H
++#define PLY_SEAT_H
++
++#include <stdarg.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <unistd.h>
++
++#include "ply-boot-splash.h"
++#include "ply-buffer.h"
++#include "ply-event-loop.h"
++#include "ply-keyboard.h"
++#include "ply-list.h"
++#include "ply-pixel-display.h"
++#include "ply-terminal.h"
++#include "ply-text-display.h"
++
++typedef struct _ply_boot_splash ply_boot_splash_t;
++typedef struct _ply_seat ply_seat_t;
++
++#ifndef PLY_HIDE_FUNCTION_DECLARATIONS
++ply_seat_t *ply_seat_new (ply_terminal_t *terminal);
++
++void ply_seat_free (ply_seat_t *seat);
<Skipped 7660 lines>
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/plymouth.git/commitdiff/0e83ad6d3eeacede31400633920f5f0d7bea4c53




More information about the pld-cvs-commit mailing list