espeaktime-now: use gst-play-event
[espeaktime] / src / daemon.c
1 #include <string.h>
2 #include <stdlib.h>
3 #include <glib.h>
4 #include <dbus/dbus-glib.h>
5 #include <dbus/dbus-glib-lowlevel.h>
6 #include <hal/libhal.h>
7
8 #include <mce/dbus-names.h>
9 #include <mce/mode-names.h>
10
11 #define HAL_COND_BUTTONPRESSED  "ButtonPressed"
12 #define HAL_BUTTON_POWER        "power"
13 #define HAL_INPUTDEV_PATH       "/org/freedesktop/Hal/devices/computer_logicaldev_input"
14
15 struct app_data {
16         DBusGConnection *bus;
17         LibHalContext *hal;
18
19         gboolean mode_locked;
20         gboolean display_on;
21 };
22
23 static void sig_tklock_mode(DBusGProxy *proxy, const char *mode, gpointer user_data)
24 {
25         struct app_data *app = user_data;
26         g_debug("sig_tklock_mode [%s]", mode);
27         app->mode_locked = !strcmp(mode, MCE_TK_LOCKED);
28 }
29
30 static void sig_display_status(DBusGProxy *proxy, const char *status, gpointer user_data)
31 {
32         struct app_data *app = user_data;
33         g_debug("sig_display_status [%s]", status);
34         app->display_on = !strcmp(status, MCE_DISPLAY_ON_STRING);
35 }
36
37 static void debug_log(const gchar *log_domain,
38         GLogLevelFlags log_level, const gchar *message, gpointer unused_data)
39 {
40         g_print("# %s\n", message);
41 }
42
43 static void power_button(struct app_data *app)
44 {
45         g_debug("power button");
46         if (app->mode_locked && app->display_on) {
47                 int res = system("espeaktime-now.sh");
48                 g_debug("speak script: %d", res);
49         }
50 }
51
52 /**
53  * Call a method with no input arguments and one string output argument.
54  * Return the allocaed result string on success, NULL on failure.
55  */
56 static char *mce_call_getstr(DBusGProxy *proxy, const char *method)
57 {
58         GError *err = NULL;
59         char *s = NULL;
60
61         if (dbus_g_proxy_call(proxy, method, &err,
62                         G_TYPE_INVALID,
63                         G_TYPE_STRING, &s, G_TYPE_INVALID))
64                 return s;
65
66         g_error("Couldn't call MCE (%s): %s\n", method, err->message);
67         g_error_free(err);
68         return NULL;
69 }
70
71 static gboolean prefill_status(struct app_data *app)
72 {
73         DBusGProxy *mce_req;
74         char *mode, *status;
75
76         mce_req = dbus_g_proxy_new_for_name(app->bus, MCE_SERVICE, MCE_REQUEST_PATH, MCE_REQUEST_IF);
77         g_assert(mce_req);
78
79         mode = mce_call_getstr(mce_req, MCE_TKLOCK_MODE_GET);
80         status = mce_call_getstr(mce_req, MCE_DISPLAY_STATUS_GET);
81         if (mode)
82                 sig_tklock_mode(NULL, mode, app);
83         if (status)
84                 sig_display_status(NULL, status, app);
85         g_free(mode);
86         g_free(status);
87         g_object_unref(mce_req);
88
89         return mode && status;
90 }
91
92 static void connect_signals(struct app_data *app)
93 {
94         DBusGProxy *mce_sig;
95
96         mce_sig = dbus_g_proxy_new_for_name(app->bus, MCE_SERVICE, MCE_SIGNAL_PATH, MCE_SIGNAL_IF);
97         g_assert(mce_sig);
98         dbus_g_proxy_add_signal(mce_sig, MCE_TKLOCK_MODE_SIG, G_TYPE_STRING, G_TYPE_INVALID);
99         dbus_g_proxy_add_signal(mce_sig, MCE_DISPLAY_SIG, G_TYPE_STRING, G_TYPE_INVALID);
100         dbus_g_proxy_connect_signal(mce_sig, MCE_TKLOCK_MODE_SIG, G_CALLBACK(sig_tklock_mode), app, NULL);
101         dbus_g_proxy_connect_signal(mce_sig, MCE_DISPLAY_SIG, G_CALLBACK(sig_display_status), app, NULL);
102 }
103
104
105 static void device_condition(LibHalContext *ctx,
106         const char *udi,
107         const char *condition_name,
108         const char *condition_detail)
109 {
110         g_debug("device_condition: name [%s] detail [%s]",
111                 condition_name, condition_detail);
112         if (!strcmp(condition_name, HAL_COND_BUTTONPRESSED) && !strcmp(condition_detail, HAL_BUTTON_POWER)) {
113                 struct app_data *app = libhal_ctx_get_user_data(ctx);
114                 power_button(app);
115         }
116 }
117
118
119 static gboolean init_hal(struct app_data *app)
120 {
121         DBusError err;
122
123         app->hal = libhal_ctx_new();
124         if (!app->hal) {
125                 g_error("Couldn't get a HAL context");
126                 return FALSE;
127         }
128         libhal_ctx_set_dbus_connection(app->hal,
129                 dbus_g_connection_get_connection(app->bus));
130         libhal_ctx_set_device_condition(app->hal, device_condition);
131         libhal_ctx_set_user_data(app->hal, app);
132
133         dbus_error_init(&err);
134         if (!libhal_ctx_init(app->hal, &err)) {
135                 g_error("Couldn't initialize HAL context: %s", err.message);
136                 dbus_error_free(&err);
137                 libhal_ctx_free(app->hal);
138                 return FALSE;
139         }
140
141         if (!libhal_device_add_property_watch(app->hal, HAL_INPUTDEV_PATH, &err)) {
142                 g_error("Couldn't add HAL watch: %s", err.message);
143                 dbus_error_free(&err);
144                 libhal_ctx_free(app->hal);
145         }
146         return TRUE;
147 }
148
149 int main(int argc, char *argv[])
150 {
151         GMainLoop *loop;
152         GError *err = NULL;
153         struct app_data app;
154
155         if (argc > 1 && !strcmp(argv[1], "-v"))
156                 g_log_set_handler(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, debug_log, NULL);
157
158         g_debug("init");
159         memset(&app, 0, sizeof(app));
160
161         g_type_init();
162         loop = g_main_loop_new(NULL, FALSE);
163
164         app.bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &err);
165         if (!app.bus) {
166                 g_error("Couldn't get DBUS connection: %s\n", err->message);
167                 g_error_free(err);
168                 return 1;
169         }
170
171         if (!init_hal(&app))
172                 return 1;
173
174         if (!prefill_status(&app))
175                 return 1;
176         connect_signals(&app);
177
178         g_debug("running");
179         g_main_loop_run(loop);
180         dbus_g_connection_unref(app.bus);
181         return 0;
182 }