2 Load applet - Maemo5 edition
7 #include <hildon/hildon.h>
8 #include <glib/gerror.h>
10 #include <glib/gstdio.h>
16 #include <dbus/dbus.h>
17 #include <dbus/dbus.h>
18 #include <dbus/dbus-glib.h>
19 #include <dbus/dbus-glib-lowlevel.h>
23 #define LOAD_APPLET_STATUS_MENU_ITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE (obj, LOAD_APPLET_TYPE_STATUS_MENU_ITEM, LoadAppletStatusMenuItemPrivate))
25 struct _LoadAppletStatusMenuItemPrivate {
38 HD_DEFINE_PLUGIN_MODULE (LoadAppletStatusMenuItem, load_applet_status_menu_item, HD_TYPE_STATUS_MENU_ITEM)
42 #define SHUTTER_SOUND "/usr/share/sounds/camera_snd_title_1.wav"
43 #define BEEP_SOUND "/usr/share/sounds/ui-default_beep.wav"
44 #define MAX_SSHOT_NAME_LEN 64
45 static gchar *sshotfilename = NULL;
46 static char sshotname[MAX_SSHOT_NAME_LEN];
47 static guint screenshot_delay = 20;
48 static guint beeps = 0;
49 static gint sshotn = 0;
50 static gint scastn = 0;
51 static gboolean taking = FALSE;
53 #define MATCH_CAMERA_KEY "type='signal'," \
54 "interface='org.freedesktop.Hal.Device',"
58 load_applet_status_menu_item_class_finalize(LoadAppletStatusMenuItemClass * klass)
63 load_applet_status_menu_item_dispose(GObject * object)
65 G_OBJECT_CLASS(load_applet_status_menu_item_parent_class)->dispose(object);
69 load_applet_status_menu_item_class_init(LoadAppletStatusMenuItemClass * klass)
71 GObjectClass *object_class = G_OBJECT_CLASS(klass);
73 object_class->dispose = load_applet_status_menu_item_dispose;
75 g_type_class_add_private(klass, sizeof(LoadAppletStatusMenuItemPrivate));
79 * Get the filename for next screen-shot. Start with nr.
83 get_next_sshot(gint nr, const gchar *suffix)
91 g_snprintf (sshotname, MAX_SSHOT_NAME_LEN-1, "%s/MyDocs/.images/%s%02d.%s", getenv("HOME"), sshotfilename, n, suffix);
92 f = g_fopen(sshotname, "r");
105 * Get the filename for next screen-cast. Start with nr.
109 get_next_scast(gint nr, const gchar *suffix)
117 g_snprintf (sshotname, MAX_SSHOT_NAME_LEN-1, "%s/MyDocs/.videos/%s%02d.%s", getenv("HOME"), "screencast", n, suffix);
118 f = g_fopen(sshotname, "r");
132 * Close the menu, make sure it is closed and redrawn
135 do_little_dance (void)
137 while (gtk_events_pending())
139 gtk_main_iteration();
148 * Take screeshot using the root window drawable
151 take_screenshot(void)
154 GdkDrawable *root_window;
157 GError *error = NULL;
160 sshotn = get_next_sshot(sshotn, "png");
163 root_window = gdk_get_default_root_window();
164 gdk_drawable_get_size(root_window, &width, &height);
165 pixbuf = gdk_pixbuf_get_from_drawable(NULL,
167 gdk_drawable_get_colormap (root_window),
173 ret = gdk_pixbuf_save(pixbuf, sshotname, "png", &error, NULL);
174 g_object_unref(pixbuf);
177 //printf("\tSaving %s\n", sshotname);
184 * Either beep or play shutter sound and make the screenshot
187 beep_or_shoot(gpointer data)
190 if (beeps >= screenshot_delay) {
191 hildon_play_system_sound(SHUTTER_SOUND);
195 hildon_play_system_sound(BEEP_SOUND);
201 static DBusHandlerResult
202 handle_dbus_events(DBusConnection *connection, DBusMessage *msg, void *user_data)
205 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
207 gint message_type = -1;
208 const gchar *interface = dbus_message_get_interface(msg);
209 const gchar *method = dbus_message_get_member(msg);
210 LoadAppletStatusMenuItem *item = (LoadAppletStatusMenuItem*)user_data;
211 item->priv = LOAD_APPLET_STATUS_MENU_ITEM_GET_PRIVATE (item);
213 if (!(message_type = dbus_message_get_type(msg)) || !interface || !method)
214 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
216 switch (message_type) {
217 case DBUS_MESSAGE_TYPE_SIGNAL:
218 if ((g_strcmp0(interface, "org.freedesktop.Hal.Device") == 0) &&
219 (g_strcmp0(method, "PropertyModified") == 0)) {
220 //Camera key pressed. Take screenshot, cancel the waiting loop, remove D-Bus listener
221 gtk_timeout_remove(item->priv->timeout);
223 hildon_play_system_sound(SHUTTER_SOUND);
225 dbus_bus_remove_match(item->priv->conn, MATCH_CAMERA_KEY, &item->priv->error);
226 dbus_connection_unref(item->priv->conn);
227 item->priv->conn = 0;
228 g_main_loop_unref(item->priv->loop);
229 item->priv->loop = NULL;
235 return DBUS_HANDLER_RESULT_HANDLED;
239 #ifdef SHOW_PROCESS_INFO
241 * Show the details dialog (FAKE)
245 activate_status_item(GtkMenuItem *item, gpointer data)
249 GtkWidget *content_area;
252 dialog = gtk_dialog_new();
254 selector = hildon_touch_selector_new_text ();
255 hildon_touch_selector_set_column_selection_mode (HILDON_TOUCH_SELECTOR (selector),HILDON_TOUCH_SELECTOR_SELECTION_MODE_SINGLE);
257 for (i = 1; i <= 10 ; i++) {
258 gchar *label = g_strdup_printf ("Item %d", i);
259 hildon_touch_selector_append_text (HILDON_TOUCH_SELECTOR (selector), label);
263 hildon_touch_selector_unselect_all(HILDON_TOUCH_SELECTOR (selector), 0);
265 content_area = GTK_DIALOG(dialog)->vbox;
266 gtk_container_add(GTK_CONTAINER(content_area), selector);
267 gtk_window_set_default_size(GTK_WINDOW(dialog), -1, 480);
269 gtk_window_set_title(GTK_WINDOW(dialog), "Select process to kill - FAKE FEATURE");
270 gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE);
271 gtk_dialog_add_button(GTK_DIALOG(dialog), "Kill it", 1);
273 gtk_widget_show_all(GTK_WIDGET(dialog));
274 //gtk_dialog_run(GTK_DIALOG(dialog)); <- blocks and won't close status menu
281 * Answer the callback by setting delayed screenshot
284 activate_delayed_screenshot_item(GtkMenuItem *item, gpointer data)
289 LoadAppletStatusMenuItem *menu_item = (LoadAppletStatusMenuItem*)data;
290 menu_item->priv = LOAD_APPLET_STATUS_MENU_ITEM_GET_PRIVATE (menu_item);
292 hildon_banner_show_information(NULL, NULL, "You have 20s to press the camera capture key to take screenshot.");
295 menu_item->priv->timeout = gtk_timeout_add(1000, beep_or_shoot, NULL);
297 menu_item->priv->loop = g_main_loop_new(NULL, FALSE);
298 dbus_error_init(&menu_item->priv->error);
299 if ((menu_item->priv->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &menu_item->priv->error)) == NULL) {
300 DLOG_CRIT("LA:Failed to open connection to system bus");
301 dbus_error_free(&menu_item->priv->error);
304 if (!dbus_connection_add_filter(menu_item->priv->conn, handle_dbus_events, (void *)data, 0)) {
305 ULOG_CRIT("LA:Failed to add dbus filter");
306 dbus_error_free(&menu_item->priv->error);
309 dbus_bus_add_match(menu_item->priv->conn, MATCH_CAMERA_KEY, &menu_item->priv->error);
310 if (dbus_error_is_set(&menu_item->priv->error)) {
311 ULOG_WARN("LA:Unable to add match for my key");
312 dbus_error_free(&menu_item->priv->error);
314 dbus_connection_setup_with_g_main(menu_item->priv->conn, NULL);
319 * Answer the callback on video button
320 * If idle, start recording
321 * If already recording, stop
324 activate_video_item(GtkMenuItem *item, gpointer data)
326 LoadAppletStatusMenuItem *la_item = (LoadAppletStatusMenuItem*)data;
330 if (la_item->priv->recording == FALSE) {
331 // We are not recording. Start recording by exec
332 scastn = get_next_scast(scastn, "avi");
333 savefile = g_strdup_printf("location=%s", sshotname);
336 execl("/usr/bin/gst-launch", "/usr/bin/gst-launch", "ximagewsrc", "!", "video/x-raw-rgb,framerate=5/1", "!", "ffmpegcolorspace", "!", "jpegenc", "quality=30", "!", "queue", "!", "mux.", "autoaudiosrc", "!", "audioconvert", "!", "audioresample", "!", "queue", "!", "mux.", "avimux", "name=mux", "!", "filesink", savefile, NULL);
339 la_item->priv->recording = TRUE;
340 la_item->priv->rec_pid = rec_pid;
343 // We are already recording
344 kill(la_item->priv->rec_pid, SIGTERM);
345 la_item->priv->recording = FALSE;
353 load_applet_status_menu_item_init (LoadAppletStatusMenuItem * menu_item)
355 #define ICON_DIR "/usr/share/pixmaps/"
356 #define ICON_VIDEO ICON_DIR"la_video.png"
357 #define ICON_PICTURE ICON_DIR"la_picture.png"
358 #define ICON_PROCESS ICON_DIR"la_process.png"
360 GtkWidget *hbox, *icon, *b;
362 menu_item->priv = LOAD_APPLET_STATUS_MENU_ITEM_GET_PRIVATE (menu_item);
364 hbox = gtk_hbox_new(FALSE, 0);
366 sshotfilename = g_strdup("screenshot");
368 #ifdef SHOW_PROCESS_INFO
370 b = hildon_button_new(HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
371 hildon_button_set_style(HILDON_BUTTON(b), HILDON_BUTTON_STYLE_PICKER);
373 icon = gtk_image_new_from_file(ICON_PROCESS);
374 gtk_widget_show(icon);
375 gtk_button_set_image(GTK_BUTTON(b), GTK_WIDGET(icon));
376 gtk_box_pack_start(GTK_BOX(hbox), b, TRUE, TRUE, 1);
377 g_signal_connect(b, "clicked", G_CALLBACK(activate_status_item), menu_item);
380 b = gtk_toggle_button_new();
382 icon = gtk_image_new_from_file(ICON_VIDEO);
383 gtk_widget_show(icon);
384 gtk_button_set_image(GTK_BUTTON(b), GTK_WIDGET(icon));
385 gtk_box_pack_start(GTK_BOX(hbox), b, TRUE, TRUE, 1);
386 menu_item->priv->screenshot_h = g_signal_connect(b, "clicked", G_CALLBACK(activate_video_item), menu_item);
388 b = hildon_button_new(HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
390 icon = gtk_image_new_from_file(ICON_PICTURE);
391 gtk_widget_show(icon);
392 gtk_button_set_image(GTK_BUTTON(b), GTK_WIDGET(icon));
393 gtk_box_pack_start(GTK_BOX(hbox), b, TRUE, TRUE, 1);
394 menu_item->priv->screenshot_h = g_signal_connect(b, "clicked", G_CALLBACK(activate_delayed_screenshot_item), menu_item);
396 // Pack widgets to menu
397 gtk_widget_show(hbox);
398 gtk_container_add(GTK_CONTAINER(menu_item), hbox);
399 gtk_widget_show(GTK_WIDGET(menu_item));
402 menu_item->priv->recording = FALSE;