From 0aefdc0f309b90d077349c261b2a496141de9197 Mon Sep 17 00:00:00 2001
From: Didier Roche <didrocks@ubuntu.com>
Date: Mon, 26 Jan 2015 17:07:32 +0100
Subject: [PATCH 04/13] Add some plymouth functionality to connect and send
 messages

Using libplymouth to connect to eventually any running plymouth instance.
Automatic reconnection attempt if plymouth was disconnected (or respawn)
when trying to send a subsequent message.
---
 Makefile.am           |  2 ++
 configure.ac          |  3 ++
 src/shared/plymouth.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/shared/plymouth.h |  6 ++++
 4 files changed, 88 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index ce8ab7e..2735ae7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -928,10 +928,12 @@ libsystemd_shared_la_CFLAGS = \
 	$(AM_CFLAGS) \
 	$(CAP_CFLAGS) \
 	$(SECCOMP_CFLAGS) \
+	$(PLYMOUTH_CFLAGS) \
 	-pthread
 
 libsystemd_shared_la_LIBADD = \
 	$(CAP_LIBS) \
+	$(PLYMOUTH_LIBS) \
 	-lm
 
 # ------------------------------------------------------------------------------
diff --git a/configure.ac b/configure.ac
index 12e4ab2..c2b8023 100644
--- a/configure.ac
+++ b/configure.ac
@@ -857,6 +857,9 @@ fi
 AM_CONDITIONAL(HAVE_MICROHTTPD, [test "$have_microhttpd" = "yes"])
 
 # ------------------------------------------------------------------------------
+PKG_CHECK_MODULES([PLYMOUTH], [ply-boot-client >= 0.8.0])
+
+# ------------------------------------------------------------------------------
 have_gnutls=no
 AC_ARG_ENABLE(gnutls, AS_HELP_STRING([--disable-gnutls], [disable gnutls support]))
 if test "x$enable_gnutls" != "xno"; then
diff --git a/src/shared/plymouth.c b/src/shared/plymouth.c
index c4865dd..7927b61 100644
--- a/src/shared/plymouth.c
+++ b/src/shared/plymouth.c
@@ -19,13 +19,90 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <ply-boot-client.h>
+
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
+#include "log.h"
 #include "plymouth.h"
 
+void plymouth_disconnected (void *user_data, ply_boot_client_t *client);
+void plymouth_update_failed(void *user_data, ply_boot_client_t *client);
+
+static ply_boot_client_t *plymouth_client = NULL;
+static ply_event_loop_t *plymouth_event_loop = NULL;
+
 bool plymouth_running(void) {
         return access("/run/plymouth/pid", F_OK) >= 0;
 }
+
+bool plymouth_connect(void) {
+
+        /* Keep existing connection */
+        if (plymouth_client)
+                return true;
+
+        /* Create the event loop */
+        if (!plymouth_event_loop)
+                plymouth_event_loop = ply_event_loop_new();
+
+        if (!plymouth_event_loop) {
+                log_error("Couldn't create event loop for plymouth");
+                return false;
+        }
+
+        plymouth_client = ply_boot_client_new();
+
+        if (!ply_boot_client_connect(plymouth_client, plymouth_disconnected, NULL)) {
+                log_error("Couldn't connect to plymouth");
+                ply_boot_client_free(plymouth_client);
+                plymouth_client = NULL;
+                plymouth_event_loop = NULL;
+                return false;
+        }
+
+        /* attach event loop after being connected to plymouth or the disconnect handler won't be register
+           and flush all events that may exists from an older connection if we are reconnected */
+        ply_boot_client_attach_to_event_loop(plymouth_client, plymouth_event_loop);
+        ply_boot_client_flush(plymouth_client);
+
+        return true;
+}
+
+void plymouth_disconnect(void) {
+        if (!plymouth_client)
+                 return;
+        ply_boot_client_disconnect(plymouth_client);
+        ply_boot_client_flush(plymouth_client);
+}
+
+void plymouth_update(const char *message) {
+        if (!plymouth_running() || !plymouth_connect())
+                return;
+
+        ply_boot_client_update_daemon(plymouth_client, message, NULL, NULL, NULL);
+        ply_boot_client_flush(plymouth_client);
+}
+
+void plymouth_delete_message(void) {
+        if (!plymouth_running() || !plymouth_client)
+                return;
+
+        ply_boot_client_tell_daemon_to_display_message (plymouth_client, "", NULL, plymouth_update_failed, NULL);
+        ply_boot_client_flush(plymouth_client);
+}
+
+void plymouth_update_failed(void *user_data, ply_boot_client_t *client) {
+        log_error("Couldn't send message to plymouth");
+}
+
+void plymouth_disconnected (void *user_data, ply_boot_client_t *client) {
+        log_warning("Plymouth disconnected");
+        plymouth_delete_message();
+        ply_boot_client_disconnect(plymouth_client);
+        ply_boot_client_free(plymouth_client);
+        plymouth_client = NULL;
+}
diff --git a/src/shared/plymouth.h b/src/shared/plymouth.h
index 39c8c37..c7c41bc 100644
--- a/src/shared/plymouth.h
+++ b/src/shared/plymouth.h
@@ -24,3 +24,9 @@
 #include <stdbool.h>
 
 bool plymouth_running(void);
+
+bool plymouth_connect(void);
+void plymouth_disconnect(void);
+void plymouth_update(const char *message);
+
+void plymouth_delete_message(void);
-- 
2.1.4

