Updated translations.
[flashlight-appl] / src / flashlight_applet.c
1 /*
2  *  Flashlight applet (widget) for Maemo.
3  *  Copyright (C) 2009 Roman Moravcik
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <glib.h>
27 #include <gtk/gtk.h>
28 #include <hildon/hildon.h>
29 #include <glib/gi18n-lib.h>
30 #include <libhal.h>
31 #include <dbus/dbus.h>
32
33 #include "flashlight_applet.h"
34 #include "flashlight_lib.h"
35
36 #define MSG_FLASHLIGHT_ON _("On")
37 #define MSG_FLASHLIGHT_OFF _("Off")
38
39 #define ICON_FLASHLIGHT_ON "statusarea_flashlight_on"
40 #define ICON_FLASHLIGHT_OFF "statusarea_flashlight_off"
41
42 #define CAM_COVER_UDI "/org/freedesktop/Hal/devices/platform_cam_shutter"
43 #define CAM_COVER_STATE "button.state.value"
44
45 #define FLASHLIGHT_STATUS_PLUGIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE (obj,   \
46                             TYPE_FLASHLIGHT_STATUS_PLUGIN, FlashlightPluginPrivate))
47
48 struct _FlashlightPluginPrivate
49 {
50         GtkWidget *button;
51         guint status_timer;
52
53         FlashlightContext_t *flashlight;
54         LibHalContext *hal;
55 };
56
57 HD_DEFINE_PLUGIN_MODULE (FlashlightPlugin, flashlight_status_plugin, HD_TYPE_STATUS_MENU_ITEM)
58
59 static gboolean flashlight_status_plugin_status (gpointer data);
60 static void flashlight_status_plugin_finalize (GObject *object);
61
62 static void
63 flashlight_status_plugin_show_notification (FlashlightPlugin *plugin,
64                                             const gchar *text)
65 {
66         FlashlightPluginPrivate *priv = FLASHLIGHT_STATUS_PLUGIN_GET_PRIVATE (plugin);
67         GtkWidget *banner;
68
69         g_return_if_fail (priv);
70
71         banner = hildon_banner_show_information (GTK_WIDGET (priv->button), NULL, text);
72         hildon_banner_set_timeout (HILDON_BANNER (banner), 9000);
73 }
74
75 static void
76 flashlight_status_plugin_enable (FlashlightPlugin *plugin,
77                                  gboolean enable)
78 {
79         FlashlightPluginPrivate *priv = FLASHLIGHT_STATUS_PLUGIN_GET_PRIVATE (plugin);
80
81         g_return_if_fail (priv);
82
83         if (enable) {
84                 if (flashlight_open (priv->flashlight, "/dev/video0") < 0) {
85                         flashlight_status_plugin_show_notification (plugin,
86                                 _("Unable to initialize flashlight.\nCamera in use by another application."));
87                         return;
88                 }
89
90                 if (flashlight_set_intensity (priv->flashlight, 1) < 0) {
91                         flashlight_status_plugin_show_notification (plugin,
92                                 _("Unable to turn on flashlight."));
93                         return;
94                 }
95
96                 hildon_button_set_value (HILDON_BUTTON (priv->button), MSG_FLASHLIGHT_ON);
97                 hildon_button_set_image (HILDON_BUTTON (priv->button),
98                                          gtk_image_new_from_icon_name (ICON_FLASHLIGHT_ON, -1));
99
100                 /* check status of controller every 1s */
101                 priv->status_timer = g_timeout_add (1000, flashlight_status_plugin_status, plugin);
102         } else {
103                 /* cancel status timer */
104                 if (priv->status_timer) {
105                         g_source_remove (priv->status_timer);
106                         priv->status_timer = 0;
107                 }
108
109                 /* set intensity to 0 */
110                 if (flashlight_set_intensity (priv->flashlight, 0) < 0) {
111                         flashlight_status_plugin_show_notification (plugin,
112                                 _("Unable to turn off flashlight."));
113                         return;
114                 }
115
116                 if (flashlight_close (priv->flashlight) < 0) {
117                         return;
118                 }
119
120                 hildon_button_set_value (HILDON_BUTTON (priv->button), MSG_FLASHLIGHT_OFF);
121                 hildon_button_set_image (HILDON_BUTTON (priv->button),
122                                          gtk_image_new_from_icon_name (ICON_FLASHLIGHT_OFF, -1));
123         }
124 }
125
126 static void
127 flashlight_status_plugin_on_hal_property_modified (LibHalContext *ctx,
128                                                    const char *udi,
129                                                    const char *key,
130                                                    dbus_bool_t is_removed,
131                                                    dbus_bool_t is_added)
132 {
133         FlashlightPlugin *plugin = libhal_ctx_get_user_data (ctx);
134         FlashlightPluginPrivate *priv = FLASHLIGHT_STATUS_PLUGIN_GET_PRIVATE (plugin);
135         gboolean is_open;
136         int intensity = 0;
137
138         g_return_if_fail (priv);
139
140         if (strcmp (udi, CAM_COVER_UDI) != 0)
141                 return;
142
143         if (strcmp (key, CAM_COVER_STATE) != 0)
144                 return;
145
146         is_open = !libhal_device_get_property_bool (ctx, udi, key, NULL);
147
148         if (is_open) {
149                 /* show widget */
150                 gtk_widget_show_all (GTK_WIDGET (plugin));
151         } else {
152                 /* turn off flashlight if flashlight is enabled */
153                 if (flashlight_get_intensity (priv->flashlight, &intensity) == 0) {
154                         if (intensity > 0) {
155                                 flashlight_status_plugin_enable (plugin, FALSE);
156                         }
157                 }
158
159                 /* hide widget */
160                 gtk_widget_hide_all (GTK_WIDGET (plugin));
161         }
162 }
163
164 static gboolean
165 flashlight_status_plugin_status (gpointer data)
166 {
167         FlashlightPlugin *plugin = data;
168         FlashlightPluginPrivate *priv = FLASHLIGHT_STATUS_PLUGIN_GET_PRIVATE (plugin);
169         int status = 0;
170
171         if (flashlight_get_status (priv->flashlight, &status) < 0) {
172                 flashlight_status_plugin_show_notification (plugin,
173                                                             _("Unable to read status from driver."));
174                 return FALSE;
175         }
176
177         /* ops, something is wrong */
178         if (status) {
179                 /* turn off flashlight */
180                 flashlight_status_plugin_enable (plugin, FALSE);
181
182                 if (status & FLASHLIGHT_STATUS_SHORT_CIRCUT_FAULT) {
183                         flashlight_status_plugin_show_notification (plugin,
184                                 _("Short-circut fault detected!\nTurning off flashlight."));
185                 } else if (status & FLASHLIGHT_STATUS_OVERTEMPERATURE_FAULT) {
186                         flashlight_status_plugin_show_notification (plugin,
187                                 _("Overtemperature fault detected!\nTurning off flashlight."));
188                 } else if (status & FLASHLIGHT_STATUS_TIMEOUT_FAULT) {
189                         flashlight_status_plugin_show_notification (plugin,
190                                 _("Timeout fault detected!\nTurning off flashlight."));
191                 } else if (status & FLASHLIGHT_STATUS_OVERVOLTAGE_FAULT) {
192                         flashlight_status_plugin_show_notification (plugin,
193                                 _("Overvoltage fault detected!\nTurning off flashlight."));
194                 }
195         }
196
197         return TRUE;
198 }
199
200 static void
201 flashlight_status_plugin_on_clicked (HildonButton *button,
202                                      gpointer data)
203 {
204         FlashlightPlugin *plugin = data;
205         FlashlightPluginPrivate *priv = FLASHLIGHT_STATUS_PLUGIN_GET_PRIVATE (plugin);
206
207         g_return_if_fail (priv);
208
209         if (!strcmp (hildon_button_get_value (button), MSG_FLASHLIGHT_ON)) {
210                 flashlight_status_plugin_enable (plugin, FALSE);
211         } else {
212                 flashlight_status_plugin_enable (plugin, TRUE);
213         }
214 }
215
216 static GtkWidget *
217 flashlight_status_plugin_ui (FlashlightPlugin *plugin)
218 {
219         GtkWidget *button;
220
221         button = hildon_button_new (HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
222         gtk_button_set_alignment (GTK_BUTTON (button), 0.0, 0.5);
223         hildon_button_set_title (HILDON_BUTTON (button), _("Flashlight"));
224         hildon_button_set_value (HILDON_BUTTON (button), MSG_FLASHLIGHT_OFF);
225         hildon_button_set_image (HILDON_BUTTON (button),
226                                  gtk_image_new_from_icon_name (ICON_FLASHLIGHT_OFF, -1));
227         hildon_button_set_image_position (HILDON_BUTTON (button), GTK_POS_LEFT);
228
229         g_signal_connect (button, "clicked",
230                                         G_CALLBACK (flashlight_status_plugin_on_clicked), plugin);
231
232         return button;
233 }
234
235 static void
236 flashlight_status_plugin_class_init (FlashlightPluginClass *class)
237 {
238         GObjectClass *object_class = G_OBJECT_CLASS (class);
239
240         object_class->finalize = flashlight_status_plugin_finalize;
241
242         g_type_class_add_private (class, sizeof (FlashlightPluginPrivate));
243 }
244
245 static void
246 flashlight_status_plugin_class_finalize (FlashlightPluginClass *class)
247 {
248 }
249
250 static void
251 flashlight_status_plugin_init (FlashlightPlugin *plugin)
252 {
253         FlashlightPluginPrivate *priv = FLASHLIGHT_STATUS_PLUGIN_GET_PRIVATE (plugin);
254         DBusConnection *dbus_connection;
255         DBusError error;
256
257         /* initialize dbus */
258         dbus_error_init (&error);
259         dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
260         if (dbus_error_is_set (&error)) {
261                 g_critical ("flashlight_status_plugin_init: Could not get the system DBus connection, %s",
262                             error.message);
263                 dbus_error_free (&error);
264                 return;
265         }
266
267         /* initialize flashlight */
268         if (flashlight_init (&priv->flashlight) < 0) {
269                 g_critical ("flashlight_status_plugin_init: Unable to create Flashlight context\n");
270                 return;
271         }
272
273         /* initialize hal */
274         priv->hal = libhal_ctx_new ();
275         if (!priv->hal) {
276                 g_critical ("flashlight_status_plugin_init: Unable to create HAL context\n");
277                 return;
278         }
279
280         libhal_ctx_set_dbus_connection (priv->hal, dbus_connection);
281         libhal_ctx_set_user_data (priv->hal, plugin);
282         libhal_ctx_set_device_property_modified (priv->hal,
283                                                  flashlight_status_plugin_on_hal_property_modified);
284
285         if (!libhal_ctx_init (priv->hal, &error)) {
286                 if (dbus_error_is_set (&error)) {
287                         g_critical ("Could not initialize the HAL context, %s",
288                                     error.message);
289                         dbus_error_free (&error);
290                 } else {
291                         g_critical ("Could not initialize the HAL context, "
292                                     "no error, is hald running?");
293                 }
294                 libhal_ctx_set_user_data (priv->hal, NULL);
295                 libhal_ctx_free (priv->hal);
296         }
297
298         libhal_device_add_property_watch (priv->hal, CAM_COVER_UDI, NULL);
299
300         /* create plugin ui */
301         priv->button = flashlight_status_plugin_ui (plugin);
302         gtk_container_add (GTK_CONTAINER (plugin), priv->button);
303
304         /* show widget if camera cover is open */
305         if ( !libhal_device_get_property_bool (priv->hal, CAM_COVER_UDI, CAM_COVER_STATE, NULL))
306                 gtk_widget_show_all (GTK_WIDGET (plugin));
307
308 }
309
310 static void
311 flashlight_status_plugin_finalize (GObject *object)
312 {
313         FlashlightPlugin *plugin = FLASHLIGHT_STATUS_PLUGIN (object);
314         FlashlightPluginPrivate *priv = FLASHLIGHT_STATUS_PLUGIN_GET_PRIVATE (plugin);
315
316         /* deinitialize hal */
317         if (priv->hal) {
318                 libhal_device_remove_property_watch (priv->hal, CAM_COVER_UDI, NULL);
319                 libhal_ctx_set_user_data (priv->hal, NULL);
320                 libhal_ctx_free (priv->hal);
321         }
322
323         /* cancel status timer */
324         if (priv->status_timer) {
325                 g_source_remove (priv->status_timer);
326         }
327
328         /* deinitialize flashlight */
329         if (priv->flashlight) {
330                 flashlight_deinit (priv->flashlight);
331         }
332
333         G_OBJECT_CLASS (flashlight_status_plugin_parent_class)->finalize (object);
334 }