2 * Camera Launcher for Maemo.
3 * Copyright (C) 2009 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 #define CAMERA_APPLICATION "camera-ui.desktop"
49 typedef struct _CLLauncherData CLLauncherData;
50 struct _CLLauncherData {
53 CLLauncherAction action;
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);
68 if (application->osso_service) {
69 if (strcmp (application->osso_service, "")) {
70 if (osso_rpc_run_with_defaults (data->osso_context,
71 application->osso_service,
74 DBUS_TYPE_INVALID) != OSSO_OK) {
77 } else if (application->exec) {
78 if (strcmp (application->exec, "")) {
79 if (!g_spawn_command_line_async (application->exec, NULL)) {
87 kill_camera_application (void)
89 system ("killall -9 camera-ui");
93 launcher_popup_selected (GtkTreeSelection *selection,
96 CLLauncherData *data = (CLLauncherData *) user_data;
100 g_return_if_fail (data);
102 if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
103 DesktopFileInfo application;
105 gtk_tree_model_get (model, &iter,
106 SELECTOR_COLUMN_NAME, &application.name,
107 SELECTOR_COLUMN_OSSO_SERVICE, &application.osso_service,
108 SELECTOR_COLUMN_EXEC, &application.exec,
111 run_application (data, &application);
114 /* destroy selector popup window */
115 launcher_popup_hide (data);
119 launcher_popup_response (GtkDialog *dialog,
123 CLLauncherData *data = (CLLauncherData *) user_data;
125 g_return_if_fail (data);
127 gtk_widget_hide_all (data->dialog);
128 gtk_widget_destroy (data->dialog);
133 launcher_popup_hide (CLLauncherData *data)
135 g_return_if_fail (data);
138 gtk_widget_hide_all (data->dialog);
139 gtk_widget_destroy (data->dialog);
145 launcher_popup_show (CLLauncherData *data)
147 GtkWidget *label, *alignment, *pannable, *tree_view;
148 GtkListStore *application_list;
149 GtkTreeViewColumn *column;
150 GtkCellRenderer *renderer;
151 GtkTreeSelection *selection;
153 g_return_if_fail (data);
156 data->dialog = gtk_dialog_new ();
157 gtk_window_set_title (GTK_WINDOW (data->dialog), _("Select application"));
158 gtk_widget_set_size_request (GTK_WIDGET (GTK_DIALOG (data->dialog)->vbox), -1, 270);
159 g_signal_connect (G_OBJECT (data->dialog), "response", G_CALLBACK (launcher_popup_response), data);
161 /* create application list */
162 application_list = gtk_list_store_new (NUM_COLS,
163 GDK_TYPE_PIXBUF, /* SELECTOR_COLUMN_ICON */
164 G_TYPE_STRING, /* SELECTOR_COLUMN_NAME */
165 G_TYPE_STRING, /* SELECTOR_COLUMN_OSSO_SERVICE */
166 G_TYPE_STRING); /* SELECTOR_COLUMN_EXEC */
168 /* get application list */
169 if (get_application_list (application_list)) {
170 GtkTreeSelection *selection;
172 /* sort list of calendars */
173 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (application_list),
174 SELECTOR_COLUMN_NAME, GTK_SORT_ASCENDING);
177 alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
178 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment),
179 0, 0, HILDON_MARGIN_DEFAULT, 0);
180 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (data->dialog)->vbox), alignment);
183 pannable = hildon_pannable_area_new ();
184 gtk_container_add (GTK_CONTAINER (alignment), pannable);
187 tree_view = hildon_gtk_tree_view_new_with_model (HILDON_UI_MODE_EDIT,
188 GTK_TREE_MODEL (application_list));
189 gtk_container_add (GTK_CONTAINER (pannable), tree_view);
191 /* application icon */
192 column = gtk_tree_view_column_new ();
193 gtk_tree_view_column_set_fixed_width (column, 75);
194 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
195 renderer = gtk_cell_renderer_pixbuf_new ();
196 g_object_set(G_OBJECT(renderer), "xpad", 10, NULL);
197 gtk_tree_view_column_pack_start (column, renderer, FALSE);
198 gtk_tree_view_column_set_attributes (column, renderer,
199 "pixbuf", SELECTOR_COLUMN_ICON,
201 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
203 /* application name */
204 column = gtk_tree_view_column_new ();
205 gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
206 renderer = gtk_cell_renderer_text_new ();
207 gtk_tree_view_column_pack_end (column, renderer, TRUE);
208 gtk_tree_view_column_set_attributes (column, renderer, "text",
209 SELECTOR_COLUMN_NAME,
211 gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
213 label = gtk_label_new (_("No applications"));
214 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (data->dialog)->vbox), label);
217 /* unref application list */
218 g_object_unref (application_list);
220 /* show selector popup */
221 gtk_widget_show_all (data->dialog);
223 /* unselect all entries */
225 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
226 gtk_tree_selection_unselect_all (selection);
227 g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (launcher_popup_selected), data);
232 camera_launcher_on_gconf_changed (GConfClient *client,
235 CLLauncherData *data)
239 CLLauncherAction action;
240 const gchar *application;
242 key = gconf_entry_get_key (entry);
243 value = gconf_entry_get_value (entry);
245 g_return_if_fail (data);
246 g_return_if_fail (value);
248 /* Only key without absolute path is required */
249 key += strlen (GCONF_CL_LAUNCHER) + 1;
251 if (!strcmp (key, "action")) {
252 action = gconf_value_get_int (value);
253 if ((action < CL_LAUNCHER_ACTION_DO_NOTHING) ||
254 (action > CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP)) {
255 g_warning("camera_launcher_on_gconf_changed: Wrong value %d of key %s/%s", action, GCONF_CL_LAUNCHER, key);
257 data->action = action;
259 } else if (!strcmp (key, "application")) {
260 application = gconf_value_get_string (value);
261 if (strcmp (application, "") &&
262 g_str_has_suffix (application, ".desktop"))
264 if (data->application)
265 g_free (data->application);
266 data->application = g_strdup (application);
268 g_warning("camera_launcher_on_gconf_changed: Wrong value %s of key %s/%s", application, GCONF_CL_LAUNCHER, key);
271 g_warning("camera_launcher_on_gconf_changed: Wrong %s key, %s", GCONF_CL_LAUNCHER, key);
273 gconf_value_free (value);
277 camera_launcher_on_hal_property_modified (LibHalContext *ctx,
280 dbus_bool_t is_removed,
281 dbus_bool_t is_added)
283 CLLauncherData *data = libhal_ctx_get_user_data (ctx);
285 DesktopFileInfo *application;
287 g_return_if_fail (data);
289 if (strcmp (key, CAM_COVER_STATE) != 0)
292 state = !libhal_device_get_property_bool (ctx, udi, key, NULL);
294 if (!strcmp (udi, CAM_COVER_UDI)) {
296 switch (data->action) {
297 case CL_LAUNCHER_ACTION_DO_NOTHING:
298 /* just only kill camera application if it's running */
299 kill_camera_application ();
302 case CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION:
303 /* kill camera application only if it's not selected as prefered */
304 if (strcmp (data->application, CAMERA_APPLICATION))
305 kill_camera_application ();
307 /* run prefered application */
308 application = get_desktop_file_info (data->application);
310 run_application (data, application);
311 g_free (application);
315 case CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP:
316 /* kill camera application if it's running */
317 kill_camera_application ();
319 /* create selector popup window */
320 launcher_popup_show (data);
324 switch (data->action) {
325 case CL_LAUNCHER_ACTION_DO_NOTHING:
326 case CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION:
330 case CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP:
331 /* destroy selector popup window */
332 launcher_popup_hide (data);
336 } else if (!strcmp (udi, CAM_FOCUS_UDI)) {
338 /* run camera application when focus key was pressed */
339 application = get_desktop_file_info (CAMERA_APPLICATION);
341 run_application (data, application);
342 g_free (application);
349 main (int argc, char **argv)
351 CLLauncherData *data;
352 DBusConnection *dbus_connection;
354 DBusError dbus_error;
355 GError *error = NULL;
357 hildon_gtk_init (&argc, &argv);
359 /* create CLLauncherData */
360 data = g_new0 (CLLauncherData, 1);
362 // data->action = CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION;
363 data->action = CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP;
364 data->application = g_strdup (CAMERA_APPLICATION);
366 /* initialize osso */
367 data->osso_context = osso_initialize (PACKAGE, VERSION, TRUE, NULL);
369 /* initialize gconf */
370 data->gconf_client = gconf_client_get_default ();
371 gconf_client_add_dir (data->gconf_client, GCONF_CL_LAUNCHER, GCONF_CLIENT_PRELOAD_ONELEVEL, &error);
373 g_warning ("camera-launcher: Unable to add GConf client, %s", error->message);
374 g_error_free (error);
378 gconf_client_notify_add (data->gconf_client, GCONF_CL_LAUNCHER,
379 (GConfClientNotifyFunc) camera_launcher_on_gconf_changed, data, NULL, &error);
381 g_warning ("camera-launcher: Unable to add GConf client notification, %s", error->message);
382 g_error_free (error);
385 gconf_client_notify (data->gconf_client, GCONF_CL_LAUNCHER "/action");
386 gconf_client_notify (data->gconf_client, GCONF_CL_LAUNCHER "/application");
388 /* initialize dbus */
389 dbus_error_init (&dbus_error);
390 dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error);
391 if (dbus_error_is_set (&dbus_error)) {
392 g_critical ("camera-launcher: Could not get the system DBus connection, %s",
394 dbus_error_free (&dbus_error);
399 hal = libhal_ctx_new ();
401 g_critical ("camera-launcher: Unable to create HAL context\n");
405 libhal_ctx_set_dbus_connection (hal, dbus_connection);
406 libhal_ctx_set_user_data (hal, data);
407 libhal_ctx_set_device_property_modified (hal, camera_launcher_on_hal_property_modified);
409 if (!libhal_ctx_init (hal, &dbus_error)) {
410 if (dbus_error_is_set (&dbus_error)) {
411 g_critical ("camera-launcher: Could not initialize the HAL context, %s",
413 dbus_error_free (&dbus_error);
415 g_critical ("camera-launcher: Could not initialize the HAL context, "
416 "no error, is hald running?");
421 libhal_device_add_property_watch (hal, CAM_COVER_UDI, NULL);
422 libhal_device_add_property_watch (hal, CAM_FOCUS_UDI, NULL);
426 /* deinitialize hal */
428 libhal_device_remove_property_watch (hal, CAM_COVER_UDI, NULL);
429 libhal_device_remove_property_watch (hal, CAM_FOCUS_UDI, NULL);
431 libhal_ctx_set_user_data (hal, NULL);
432 libhal_ctx_shutdown (hal, NULL);
433 libhal_ctx_free (hal);
437 /* deinitialize osso */
438 if (data->osso_context) {
439 osso_deinitialize (data->osso_context);