X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fcl-launcher.c;fp=src%2Fcl-launcher.c;h=4d735bc3f24747793143b3049fc9a25bf7e885c9;hb=9ff94de5585c86d4a7e6dc00640fa923d8b68479;hp=0000000000000000000000000000000000000000;hpb=c00fd0d00e89489abab6d6028fb34fce43dec8f2;p=cl-launcher diff --git a/src/cl-launcher.c b/src/cl-launcher.c new file mode 100644 index 0000000..4d735bc --- /dev/null +++ b/src/cl-launcher.c @@ -0,0 +1,443 @@ +/* + * Camera Launcher for Maemo. + * Copyright (C) 2009 Roman Moravcik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +#include "cl-utils.h" + +#define CAM_COVER_UDI "/org/freedesktop/Hal/devices/platform_cam_shutter" +#define CAM_FOCUS_UDI "/org/freedesktop/Hal/devices/platform_cam_focus" +#define CAM_COVER_STATE "button.state.value" + +#define CAMERA_APPLICATION "camera-ui.desktop" + +typedef struct _CLLauncherData CLLauncherData; +struct _CLLauncherData { + GtkWidget *dialog; + + CLLauncherAction action; + gchar *application; + + osso_context_t *osso_context; + GConfClient *gconf_client; +}; + +static void launcher_popup_show (CLLauncherData *data); +static void launcher_popup_hide (CLLauncherData *data); + +static void +run_application (CLLauncherData *data, DesktopFileInfo *application) +{ + g_return_if_fail (data); + + if (application->osso_service) { + if (strcmp (application->osso_service, "")) { + if (osso_rpc_run_with_defaults (data->osso_context, + application->osso_service, + "top_application", + NULL, + DBUS_TYPE_INVALID) != OSSO_OK) { + } + } + } else if (application->exec) { + if (strcmp (application->exec, "")) { + if (!g_spawn_command_line_async (application->exec, NULL)) { + } + } + } else { + } +} + +static void +kill_camera_application (void) +{ + system ("killall -9 camera-ui"); +} + +static void +launcher_popup_selected (GtkTreeSelection *selection, + gpointer user_data) +{ + CLLauncherData *data = (CLLauncherData *) user_data; + GtkTreeModel *model; + GtkTreeIter iter; + + g_return_if_fail (data); + + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + DesktopFileInfo application; + + gtk_tree_model_get (model, &iter, + SELECTOR_COLUMN_NAME, &application.name, + SELECTOR_COLUMN_OSSO_SERVICE, &application.osso_service, + SELECTOR_COLUMN_EXEC, &application.exec, + -1); + + run_application (data, &application); + } + + /* destroy selector popup window */ + launcher_popup_hide (data); +} + +static void +launcher_popup_response (GtkDialog *dialog, + gint response_id, + gpointer user_data) +{ + CLLauncherData *data = (CLLauncherData *) user_data; + + g_return_if_fail (data); + + gtk_widget_hide_all (data->dialog); + gtk_widget_destroy (data->dialog); + data->dialog = NULL; +} + +static void +launcher_popup_hide (CLLauncherData *data) +{ + g_return_if_fail (data); + + if (data->dialog) { + gtk_widget_hide_all (data->dialog); + gtk_widget_destroy (data->dialog); + data->dialog = NULL; + } +} + +static void +launcher_popup_show (CLLauncherData *data) +{ + GtkWidget *label, *alignment, *pannable, *tree_view; + GtkListStore *application_list; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkTreeSelection *selection; + + g_return_if_fail (data); + + /* popup dialog */ + data->dialog = gtk_dialog_new (); + gtk_window_set_title (GTK_WINDOW (data->dialog), _("Select application")); + gtk_widget_set_size_request (GTK_WIDGET (GTK_DIALOG (data->dialog)->vbox), -1, 270); + g_signal_connect (G_OBJECT (data->dialog), "response", G_CALLBACK (launcher_popup_response), data); + + /* create application list */ + application_list = gtk_list_store_new (NUM_COLS, + GDK_TYPE_PIXBUF, /* SELECTOR_COLUMN_ICON */ + G_TYPE_STRING, /* SELECTOR_COLUMN_NAME */ + G_TYPE_STRING, /* SELECTOR_COLUMN_OSSO_SERVICE */ + G_TYPE_STRING); /* SELECTOR_COLUMN_EXEC */ + + /* get application list */ + if (get_application_list (application_list)) { + GtkTreeSelection *selection; + + /* sort list of calendars */ + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (application_list), + SELECTOR_COLUMN_NAME, GTK_SORT_ASCENDING); + + /* alignment */ + alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), + 0, 0, HILDON_MARGIN_DEFAULT, 0); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (data->dialog)->vbox), alignment); + + /* pannable */ + pannable = hildon_pannable_area_new (); + gtk_container_add (GTK_CONTAINER (alignment), pannable); + + /* tree view */ + tree_view = hildon_gtk_tree_view_new_with_model (HILDON_UI_MODE_EDIT, + GTK_TREE_MODEL (application_list)); + gtk_container_add (GTK_CONTAINER (pannable), tree_view); + + /* application icon */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_fixed_width (column, 75); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); + renderer = gtk_cell_renderer_pixbuf_new (); + g_object_set(G_OBJECT(renderer), "xpad", 10, NULL); + gtk_tree_view_column_pack_start (column, renderer, FALSE); + gtk_tree_view_column_set_attributes (column, renderer, + "pixbuf", SELECTOR_COLUMN_ICON, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); + + /* application name */ + column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_end (column, renderer, TRUE); + gtk_tree_view_column_set_attributes (column, renderer, "text", + SELECTOR_COLUMN_NAME, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column); + } else { + label = gtk_label_new (_("No applications")); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (data->dialog)->vbox), label); + } + + /* unref application list */ + g_object_unref (application_list); + + /* show selector popup */ + gtk_widget_show_all (data->dialog); + + /* unselect all entries */ + if (tree_view) { + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view)); + gtk_tree_selection_unselect_all (selection); + g_signal_connect (G_OBJECT (selection), "changed", G_CALLBACK (launcher_popup_selected), data); + } +} + +static void +camera_launcher_on_gconf_changed (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + CLLauncherData *data) +{ + const gchar *key; + GConfValue *value; + CLLauncherAction action; + const gchar *application; + + key = gconf_entry_get_key (entry); + value = gconf_entry_get_value (entry); + + g_return_if_fail (data); + g_return_if_fail (value); + + /* Only key without absolute path is required */ + key += strlen (GCONF_CL_LAUNCHER) + 1; + + if (!strcmp (key, "action")) { + action = gconf_value_get_int (value); + if ((action < CL_LAUNCHER_ACTION_DO_NOTHING) || + (action > CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP)) { + g_warning("camera_launcher_on_gconf_changed: Wrong value %d of key %s/%s", action, GCONF_CL_LAUNCHER, key); + } else { + data->action = action; + } + } else if (!strcmp (key, "application")) { + application = gconf_value_get_string (value); + if (strcmp (application, "") && + g_str_has_suffix (application, ".desktop")) + { + if (data->application) + g_free (data->application); + data->application = g_strdup (application); + } else { + g_warning("camera_launcher_on_gconf_changed: Wrong value %s of key %s/%s", application, GCONF_CL_LAUNCHER, key); + } + } else { + g_warning("camera_launcher_on_gconf_changed: Wrong %s key, %s", GCONF_CL_LAUNCHER, key); + } + gconf_value_free (value); +} + +static void +camera_launcher_on_hal_property_modified (LibHalContext *ctx, + const char *udi, + const char *key, + dbus_bool_t is_removed, + dbus_bool_t is_added) +{ + CLLauncherData *data = libhal_ctx_get_user_data (ctx); + gboolean state; + DesktopFileInfo *application; + + g_return_if_fail (data); + + if (strcmp (key, CAM_COVER_STATE) != 0) + return; + + state = !libhal_device_get_property_bool (ctx, udi, key, NULL); + + if (!strcmp (udi, CAM_COVER_UDI)) { + if (state) { + switch (data->action) { + case CL_LAUNCHER_ACTION_DO_NOTHING: + /* just only kill camera application if it's running */ + kill_camera_application (); + break; + + case CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION: + /* kill camera application only if it's not selected as prefered */ + if (strcmp (data->application, CAMERA_APPLICATION)) + kill_camera_application (); + + /* run prefered application */ + application = get_desktop_file_info (data->application); + if (application) { + run_application (data, application); + g_free (application); + } + break; + + case CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP: + /* kill camera application if it's running */ + kill_camera_application (); + + /* create selector popup window */ + launcher_popup_show (data); + break; + } + } else { + switch (data->action) { + case CL_LAUNCHER_ACTION_DO_NOTHING: + case CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION: + /* do nothing */ + break; + + case CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP: + /* destroy selector popup window */ + launcher_popup_hide (data); + break; + } + } + } else if (!strcmp (udi, CAM_FOCUS_UDI)) { + if (state) { + /* run camera application when focus key was pressed */ + application = get_desktop_file_info (CAMERA_APPLICATION); + if (application) { + run_application (data, application); + g_free (application); + } + } + } +} + +int +main (int argc, char **argv) +{ + CLLauncherData *data; + DBusConnection *dbus_connection; + LibHalContext *hal; + DBusError dbus_error; + GError *error = NULL; + + hildon_gtk_init (&argc, &argv); + + /* create CLLauncherData */ + data = g_new0 (CLLauncherData, 1); + data->dialog = NULL; +// data->action = CL_LAUNCHER_ACTION_RUN_PREFERED_APPLICATION; + data->action = CL_LAUNCHER_ACTION_SHOW_SELECTOR_POPUP; + data->application = g_strdup (CAMERA_APPLICATION); + + /* initialize osso */ + data->osso_context = osso_initialize (PACKAGE, VERSION, TRUE, NULL); + + /* initialize gconf */ + data->gconf_client = gconf_client_get_default (); + gconf_client_add_dir (data->gconf_client, GCONF_CL_LAUNCHER, GCONF_CLIENT_PRELOAD_ONELEVEL, &error); + if (error) { + g_warning ("camera-launcher: Unable to add GConf client, %s", error->message); + g_error_free (error); + error = NULL; + } + + gconf_client_notify_add (data->gconf_client, GCONF_CL_LAUNCHER, + (GConfClientNotifyFunc) camera_launcher_on_gconf_changed, data, NULL, &error); + if (error) { + g_warning ("camera-launcher: Unable to add GConf client notification, %s", error->message); + g_error_free (error); + } + + gconf_client_notify (data->gconf_client, GCONF_CL_LAUNCHER "/action"); + gconf_client_notify (data->gconf_client, GCONF_CL_LAUNCHER "/application"); + + /* initialize dbus */ + dbus_error_init (&dbus_error); + dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error); + if (dbus_error_is_set (&dbus_error)) { + g_critical ("camera-launcher: Could not get the system DBus connection, %s", + dbus_error.message); + dbus_error_free (&dbus_error); + goto osso_error; + } + + /* initialize hal */ + hal = libhal_ctx_new (); + if (!hal) { + g_critical ("camera-launcher: Unable to create HAL context\n"); + goto osso_error; + } + + libhal_ctx_set_dbus_connection (hal, dbus_connection); + libhal_ctx_set_user_data (hal, data); + libhal_ctx_set_device_property_modified (hal, camera_launcher_on_hal_property_modified); + + if (!libhal_ctx_init (hal, &dbus_error)) { + if (dbus_error_is_set (&dbus_error)) { + g_critical ("camera-launcher: Could not initialize the HAL context, %s", + dbus_error.message); + dbus_error_free (&dbus_error); + } else { + g_critical ("camera-launcher: Could not initialize the HAL context, " + "no error, is hald running?"); + } + goto hal_error; + } + + libhal_device_add_property_watch (hal, CAM_COVER_UDI, NULL); + libhal_device_add_property_watch (hal, CAM_FOCUS_UDI, NULL); + + gtk_main (); + + /* deinitialize hal */ + if (hal) { + libhal_device_remove_property_watch (hal, CAM_COVER_UDI, NULL); + libhal_device_remove_property_watch (hal, CAM_FOCUS_UDI, NULL); +hal_error: + libhal_ctx_set_user_data (hal, NULL); + libhal_ctx_shutdown (hal, NULL); + libhal_ctx_free (hal); + } + +osso_error: + /* deinitialize osso */ + if (data->osso_context) { + osso_deinitialize (data->osso_context); + } + + return 0; +}