+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <hal/libhal.h>
+
+#include <mce/dbus-names.h>
+#include <mce/mode-names.h>
+
+#define HAL_COND_BUTTONPRESSED "ButtonPressed"
+#define HAL_BUTTON_POWER "power"
+#define HAL_INPUTDEV_PATH "/org/freedesktop/Hal/devices/computer_logicaldev_input"
+
+struct app_data {
+ DBusGConnection *bus;
+ LibHalContext *hal;
+
+ gboolean mode_locked;
+ gboolean display_on;
+};
+
+static void sig_tklock_mode(DBusGProxy *proxy, const char *mode, gpointer user_data)
+{
+ struct app_data *app = user_data;
+ g_debug("sig_tklock_mode [%s]", mode);
+ app->mode_locked = !strcmp(mode, MCE_TK_LOCKED);
+}
+
+static void sig_display_status(DBusGProxy *proxy, const char *status, gpointer user_data)
+{
+ struct app_data *app = user_data;
+ g_debug("sig_display_status [%s]", status);
+ app->display_on = !strcmp(status, MCE_DISPLAY_ON_STRING);
+}
+
+static void debug_log(const gchar *log_domain,
+ GLogLevelFlags log_level, const gchar *message, gpointer unused_data)
+{
+ g_print("# %s\n", message);
+}
+
+static void power_button(struct app_data *app)
+{
+ g_debug("power button");
+ if (app->mode_locked && app->display_on) {
+ int res = system("espeaktime-now.sh");
+ g_debug("speak script: %d", res);
+ }
+}
+
+/**
+ * Call a method with no input arguments and one string output argument.
+ * Return the allocaed result string on success, NULL on failure.
+ */
+static char *mce_call_getstr(DBusGProxy *proxy, const char *method)
+{
+ GError *err = NULL;
+ char *s = NULL;
+
+ if (dbus_g_proxy_call(proxy, method, &err,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, &s, G_TYPE_INVALID))
+ return s;
+
+ g_error("Couldn't call MCE (%s): %s\n", method, err->message);
+ g_error_free(err);
+ return NULL;
+}
+
+static gboolean prefill_status(struct app_data *app)
+{
+ DBusGProxy *mce_req;
+ char *mode, *status;
+
+ mce_req = dbus_g_proxy_new_for_name(app->bus, MCE_SERVICE, MCE_REQUEST_PATH, MCE_REQUEST_IF);
+ g_assert(mce_req);
+
+ mode = mce_call_getstr(mce_req, MCE_TKLOCK_MODE_GET);
+ status = mce_call_getstr(mce_req, MCE_DISPLAY_STATUS_GET);
+ if (mode)
+ sig_tklock_mode(NULL, mode, app);
+ if (status)
+ sig_display_status(NULL, status, app);
+ g_free(mode);
+ g_free(status);
+ g_object_unref(mce_req);
+
+ return mode && status;
+}
+
+static void connect_signals(struct app_data *app)
+{
+ DBusGProxy *mce_sig;
+
+ mce_sig = dbus_g_proxy_new_for_name(app->bus, MCE_SERVICE, MCE_SIGNAL_PATH, MCE_SIGNAL_IF);
+ g_assert(mce_sig);
+ dbus_g_proxy_add_signal(mce_sig, MCE_TKLOCK_MODE_SIG, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(mce_sig, MCE_DISPLAY_SIG, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(mce_sig, MCE_TKLOCK_MODE_SIG, G_CALLBACK(sig_tklock_mode), app, NULL);
+ dbus_g_proxy_connect_signal(mce_sig, MCE_DISPLAY_SIG, G_CALLBACK(sig_display_status), app, NULL);
+}
+
+
+static void device_condition(LibHalContext *ctx,
+ const char *udi,
+ const char *condition_name,
+ const char *condition_detail)
+{
+ g_debug("device_condition: name [%s] detail [%s]",
+ condition_name, condition_detail);
+ if (!strcmp(condition_name, HAL_COND_BUTTONPRESSED) && !strcmp(condition_detail, HAL_BUTTON_POWER)) {
+ struct app_data *app = libhal_ctx_get_user_data(ctx);
+ power_button(app);
+ }
+}
+
+
+static gboolean init_hal(struct app_data *app)
+{
+ DBusError err;
+
+ app->hal = libhal_ctx_new();
+ if (!app->hal) {
+ g_error("Couldn't get a HAL context");
+ return FALSE;
+ }
+ libhal_ctx_set_dbus_connection(app->hal,
+ dbus_g_connection_get_connection(app->bus));
+ libhal_ctx_set_device_condition(app->hal, device_condition);
+ libhal_ctx_set_user_data(app->hal, app);
+
+ dbus_error_init(&err);
+ if (!libhal_ctx_init(app->hal, &err)) {
+ g_error("Couldn't initialize HAL context: %s", err.message);
+ dbus_error_free(&err);
+ libhal_ctx_free(app->hal);
+ return FALSE;
+ }
+
+ if (!libhal_device_add_property_watch(app->hal, HAL_INPUTDEV_PATH, &err)) {
+ g_error("Couldn't add HAL watch: %s", err.message);
+ dbus_error_free(&err);
+ libhal_ctx_free(app->hal);
+ }
+ return TRUE;
+}
+
int main(int argc, char *argv[])
{
+ GMainLoop *loop;
+ GError *err = NULL;
+ struct app_data app;
+
+ if (argc > 1 && !strcmp(argv[1], "-d"))
+ g_log_set_handler(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, debug_log, NULL);
+
+ g_debug("init");
+ memset(&app, 0, sizeof(app));
+
+ g_type_init();
+ loop = g_main_loop_new(NULL, FALSE);
+
+ app.bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err);
+ if (!app.bus) {
+ g_error("Couldn't get DBUS connection: %s\n", err->message);
+ g_error_free(err);
+ return 1;
+ }
+
+ if (!init_hal(&app))
+ return 1;
+
+ if (!prefill_status(&app))
+ return 1;
+ connect_signals(&app);
+
+ g_debug("running");
+ g_main_loop_run(loop);
+ dbus_g_connection_unref(app.bus);
return 0;
}