2 * Camera Launcher for Maemo.
3 * Copyright (C) 2010 Roman Moravcik
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.
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.
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
28 #include <gconf/gconf-client.h>
31 #include <glib/gi18n-lib.h>
34 #include <hildon/hildon.h>
39 #include <dbus/dbus.h>
43 #define CAM_COVER_UDI "/org/freedesktop/Hal/devices/platform_cam_shutter"
44 #define CAM_FOCUS_UDI "/org/freedesktop/Hal/devices/platform_cam_focus"
45 #define CAM_COVER_STATE "button.state.value"
47 typedef struct _CLLauncherData CLLauncherData;
48 struct _CLLauncherData {
51 CLLauncherAction action;
52 gchar *prefered_application;
53 GtkListStore *application_list;
54 gboolean application_list_empty;
56 osso_context_t *osso_context;
57 GConfClient *gconf_client;
60 static void launcher_popup_show (CLLauncherData *data);
61 static void launcher_popup_hide (CLLauncherData *data);
64 run_application (CLLauncherData *data, DesktopFileInfo *application)
66 g_return_if_fail (data);
67 g_return_if_fail (data->osso_context);
69 if (application->osso_service) {
70 if (strcmp (application->osso_service, "")) {
71 if (osso_rpc_run_with_defaults (data->osso_context,
72 application->osso_service,
75 DBUS_TYPE_INVALID) != OSSO_OK) {
78 } else if (application->exec) {
79 if (strcmp (application->exec, "")) {
80 if (!g_spawn_command_line_async (application->exec, NULL)) {
88 kill_camera_application (void)
90 system ("killall -9 camera-ui");
94 launcher_popup_selected (GtkTreeSelection *selection,
97 CLLauncherData *data = (CLLauncherData *) user_data;
101 g_return_if_fail (data);
103 if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
104 DesktopFileInfo application;
106 gtk_tree_model_get (model, &iter,
107 SELECTOR_COLUMN_NAME, &application.name,
108 SELECTOR_COLUMN_OSSO_SERVICE, &application.osso_service,
109 SELECTOR_COLUMN_EXEC, &application.exec,
112 run_application (data, &application);
115 /* destroy selector popup window */
116 launcher_popup_hide (data);
120 launcher_popup_response (GtkDialog *dialog,
124 CLLauncherData *data = (CLLauncherData *) user_data;
126 g_return_if_fail (data);
127 g_return_if_fail (data->dialog);
129 gtk_widget_hide_all (data->dialog);
130 gtk_widget_destroy (data->dialog);
135 launcher_popup_hide (CLLauncherData *data)
137 g_return_if_fail (data);
140 gtk_widget_hide_all (data->dialog);
141 gtk_widget_destroy (data->dialog);
147 launcher_popup_show (CLLauncherData *data)
149 GtkWidget *label, *alignment, *pannable, *tree_view;
150 GtkTreeViewColumn *column;
151 GtkCellRenderer *renderer;
152 GtkTreeSelection *selection;
154 g_return_if_fail (data);
157 data->dialog = gtk_dialog_new ();
158 gtk_window_set_title (GTK_WINDOW (data->dialog), _("Select application"));
159 gtk_widget_set_size_request (GTK_WIDGET (GTK_DIALOG (data->dialog)->vbox), -1, 292);
160 hildon_gtk_window_set_portrait_flags (GTK_WINDOW (data->dialog), HILDON_PORTRAIT_MODE_SUPPORT);
161 g_signal_connect (G_OBJECT (data->dialog), "response", G_CALLBACK (launcher_popup_response), data);
163 /* check if application list is empty */
164 if (!data->application_list_empty) {
165 GtkTreeSelection *selection;
167 /* sort list of applications */
168 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (data->application_list),
169 SELECTOR_COLUMN_NAME, GTK_SORT_ASCENDING);
172 alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
173 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
174 0, 0, HILDON_MARGIN_DEFAULT, 0);
175 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (data->dialog)->vbox), alignment);
178 pannable = hildon_pannable_area_new ();
179 gtk_container_add (GTK_CONTAINER (alignment), pannable);
182 tree_view = hildon_gtk_tree_view_new_with_model (HILDON_UI_MODE_EDIT,
183 GTK_TREE_MODEL (data->application_list));
184 gtk_container_add (GTK_CONTAINER (pannable), tree_view);
186 /* application icon */
187 column = gtk_tree_view_column_new ();
188 gtk_tree_view_column_set_fixed_width (column, 75);
189 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
190 renderer = gtk_cell_renderer_pixbuf_new ();
191 g_object_set(G_OBJECT(renderer), "xpad", 10, NULL);
192 gtk_tree_view_column_pack_start (column, renderer, FALSE);
193 gtk_tree_view_column_set_attributes (column, renderer,
194 "pixbuf", SELECTOR_COLUMN_ICON,
196 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
198 /* application name */
199 column = gtk_tree_view_column_new ();
200 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
201 renderer = gtk_cell_renderer_text_new ();
202 gtk_tree_view_column_pack_end (column, renderer, TRUE);
203 gtk_tree_view_column_set_attributes (column, renderer, "text",
204 SELECTOR_COLUMN_NAME,
206 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
208 label = gtk_label_new (_("No applications"));
209 hildon_helper_set_logical_color (label, GTK_RC_FG, GTK_STATE_NORMAL,
210 "SecondaryTextColor");
211 hildon_helper_set_logical_font (label, "LargeSystemFont");
212 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (data->dialog)->vbox), label);
215 /* show selector popup */
216 gtk_widget_show_all (data->dialog);
218 /* unselect all entries */
220 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
221 gtk_tree_selection_unselect_all (selection);
222 g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (launcher_popup_selected), data);
227 camera_launcher_on_gconf_changed (GConfClient *client,
230 CLLauncherData *data)
234 CLLauncherAction action;
235 const gchar *application;
236 const GSList *application_list;
238 g_return_if_fail (data);
240 key = gconf_entry_get_key (entry);
241 value = gconf_entry_get_value (entry);
243 g_return_if_fail (value);
245 /* Only key without absolute path is required */
246 key += strlen (GCONF_CL_LAUNCHER) + 1;
248 if (!strcmp (key, "action")) {
249 action = gconf_value_get_int (value);
250 if ((action < CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION) ||
251 (action > CL_LAUNCHER_ACTION_DO_NOTHING)) {
252 g_warning("camera_launcher_on_gconf_changed: Wrong value %d of key %s/%s", action,
253 GCONF_CL_LAUNCHER, key);
255 data->action = action;
257 } else if (!strcmp (key, "prefered_application")) {
258 application = gconf_value_get_string (value);
259 if (strcmp (application, "") &&
260 g_str_has_suffix (application, ".desktop"))
262 if (data->prefered_application)
263 g_free (data->prefered_application);
264 data->prefered_application = g_strdup (application);
266 g_warning("camera_launcher_on_gconf_changed: Wrong value %s of key %s/%s", application,
267 GCONF_CL_LAUNCHER, key);
269 } else if (!strcmp (key, "application_list")) {
270 if (data->application_list) {
271 if (gconf_value_get_list_type (value) == GCONF_VALUE_STRING) {
272 application_list = gconf_value_get_list (value);
274 /* clear previous application list */
275 gtk_list_store_clear (data->application_list);
277 /* fill application list */
278 data->application_list_empty = get_application_list_from_list (data->application_list,
283 g_warning("camera_launcher_on_gconf_changed: Wrong %s key, %s", GCONF_CL_LAUNCHER, key);
288 camera_launcher_on_hal_property_modified (LibHalContext *ctx,
291 dbus_bool_t is_removed,
292 dbus_bool_t is_added)
294 CLLauncherData *data = libhal_ctx_get_user_data (ctx);
296 DesktopFileInfo *application;
298 g_return_if_fail (data);
300 if (strcmp (key, CAM_COVER_STATE) != 0)
303 state = !libhal_device_get_property_bool (ctx, udi, key, NULL);
305 if (!strcmp (udi, CAM_COVER_UDI)) {
307 switch (data->action) {
308 case CL_LAUNCHER_ACTION_DO_NOTHING:
309 /* just only kill camera application if it's running */
310 kill_camera_application ();
313 case CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION:
314 /* kill camera application only if it's not selected as prefered */
315 if (strcmp (data->prefered_application, CAMERA_APPLICATION_DESKTOP_FILE))
316 kill_camera_application ();
318 /* run prefered application */
319 application = get_desktop_file_info (data->prefered_application);
321 run_application (data, application);
322 g_free (application);
326 case CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP:
327 /* kill camera application if it's running */
328 kill_camera_application ();
330 /* create selector popup window */
331 launcher_popup_show (data);
335 switch (data->action) {
336 case CL_LAUNCHER_ACTION_DO_NOTHING:
337 case CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION:
341 case CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP:
342 /* destroy selector popup window */
343 launcher_popup_hide (data);
347 } else if (!strcmp (udi, CAM_FOCUS_UDI)) {
349 /* run camera application when focus key was pressed */
350 application = get_desktop_file_info (CAMERA_APPLICATION_DESKTOP_FILE);
352 run_application (data, application);
353 g_free (application);
360 main (int argc, char **argv)
362 CLLauncherData *data;
363 DBusConnection *dbus_connection;
365 DBusError dbus_error;
366 GError *error = NULL;
368 hildon_gtk_init (&argc, &argv);
370 /* allocate cllauncherdata */
371 data = g_new0 (CLLauncherData, 1);
373 data->action = CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION;
374 data->prefered_application = g_strdup (CAMERA_APPLICATION_DESKTOP_FILE);
375 data->application_list = gtk_list_store_new (NUM_COLS,
376 G_TYPE_STRING, /* SELECTOR_COLUMN_FILENAME */
377 GDK_TYPE_PIXBUF, /* SELECTOR_COLUMN_ICON */
378 G_TYPE_STRING, /* SELECTOR_COLUMN_NAME */
379 G_TYPE_STRING, /* SELECTOR_COLUMN_OSSO_SERVICE */
380 G_TYPE_STRING); /* SELECTOR_COLUMN_EXEC */
381 data->application_list_empty = TRUE;
383 /* initialize osso */
384 data->osso_context = osso_initialize (PACKAGE, VERSION, TRUE, NULL);
386 /* initialize gconf */
387 data->gconf_client = gconf_client_get_default ();
388 gconf_client_add_dir (data->gconf_client, GCONF_CL_LAUNCHER, GCONF_CLIENT_PRELOAD_ONELEVEL, &error);
390 g_warning ("camera-launcher: Unable to add GConf client, %s", error->message);
391 g_error_free (error);
395 gconf_client_notify_add (data->gconf_client, GCONF_CL_LAUNCHER,
396 (GConfClientNotifyFunc) camera_launcher_on_gconf_changed, data, NULL, &error);
398 g_warning ("camera-launcher: Unable to add GConf client notification, %s", error->message);
399 g_error_free (error);
402 gconf_client_notify (data->gconf_client, GCONF_CL_LAUNCHER "/action");
403 gconf_client_notify (data->gconf_client, GCONF_CL_LAUNCHER "/prefered_application");
404 gconf_client_notify (data->gconf_client, GCONF_CL_LAUNCHER "/application_list");
406 /* initialize dbus */
407 dbus_error_init (&dbus_error);
408 dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error);
409 if (dbus_error_is_set (&dbus_error)) {
410 g_critical ("camera-launcher: Could not get the system DBus connection, %s",
412 dbus_error_free (&dbus_error);
417 hal = libhal_ctx_new ();
419 g_critical ("camera-launcher: Unable to create HAL context\n");
423 libhal_ctx_set_dbus_connection (hal, dbus_connection);
424 libhal_ctx_set_user_data (hal, data);
425 libhal_ctx_set_device_property_modified (hal, camera_launcher_on_hal_property_modified);
427 if (!libhal_ctx_init (hal, &dbus_error)) {
428 if (dbus_error_is_set (&dbus_error)) {
429 g_critical ("camera-launcher: Could not initialize the HAL context, %s",
431 dbus_error_free (&dbus_error);
433 g_critical ("camera-launcher: Could not initialize the HAL context, "
434 "no error, is hald running?");
439 libhal_device_add_property_watch (hal, CAM_COVER_UDI, NULL);
440 /* libhal_device_add_property_watch (hal, CAM_FOCUS_UDI, NULL); */
444 /* deinitialize hal */
446 libhal_device_remove_property_watch (hal, CAM_COVER_UDI, NULL);
447 /* libhal_device_remove_property_watch (hal, CAM_FOCUS_UDI, NULL); */
449 libhal_ctx_set_user_data (hal, NULL);
450 libhal_ctx_shutdown (hal, NULL);
451 libhal_ctx_free (hal);
454 /* unreference dbus connection */
456 dbus_connection_unref (dbus_connection);
459 /* deinitialize osso */
460 if (data->osso_context) {
461 osso_deinitialize (data->osso_context);
464 /* free cllauncherdata */
466 if (data->prefered_application)
467 g_free (data->prefered_application);
469 /* unref application list */
470 g_object_unref (data->application_list);