2 * Entangle: Tethered Camera Control & Capture
4 * Copyright (C) 2009-2012 Daniel P. Berrange
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <glib/gi18n.h>
32 #include "entangle-debug.h"
33 #include "entangle-camera-manager.h"
34 #include "entangle-camera-list.h"
35 #include "entangle-camera-info.h"
36 #include "entangle-camera-support.h"
37 #include "entangle-camera-picker.h"
38 #include "entangle-session.h"
39 #include "entangle-image-display.h"
40 #include "entangle-image-statusbar.h"
41 #include "entangle-image-loader.h"
42 #include "entangle-thumbnail-loader.h"
43 #include "entangle-image-popup.h"
44 #include "entangle-image-histogram.h"
45 #include "entangle-help-about.h"
46 #include "entangle-session-browser.h"
47 #include "entangle-control-panel.h"
48 #include "entangle-colour-profile.h"
49 #include "entangle-preferences-display.h"
50 #include "entangle-progress.h"
51 #include "entangle-dpms.h"
52 #include "entangle-window.h"
53 #include "entangle-auto-drawer.h"
55 #define ENTANGLE_CAMERA_MANAGER_GET_PRIVATE(obj) \
56 (G_TYPE_INSTANCE_GET_PRIVATE((obj), ENTANGLE_TYPE_CAMERA_MANAGER, EntangleCameraManagerPrivate))
58 struct _EntangleCameraManagerPrivate {
59 EntangleCamera *camera;
61 gboolean cameraChanged;
62 EntangleSession *session;
64 EntangleCameraPicker *picker;
65 EntangleHelpAbout *about;
67 EntangleCameraInfo *summary;
68 EntangleCameraInfo *manual;
69 EntangleCameraInfo *driver;
70 EntangleCameraSupport *supported;
72 EntangleImageLoader *imageLoader;
73 EntangleThumbnailLoader *thumbLoader;
74 EntangleColourProfileTransform *colourTransform;
75 GtkScrolledWindow *imageScroll;
76 EntangleImageDisplay *imageDisplay;
77 EntangleImageStatusbar *imageStatusbar;
78 EntangleAutoDrawer *imageDrawer;
79 gulong imageDrawerTimer;
80 EntangleSessionBrowser *sessionBrowser;
81 GtkMenu *sessionBrowserMenu;
82 EntangleImage *sessionBrowserImage;
83 EntangleControlPanel *controlPanel;
84 EntanglePreferencesDisplay *prefsDisplay;
85 EntangleImageHistogram *imageHistogram;
87 EntangleImage *currentImage;
89 EntangleImagePopup *imagePresentation;
90 gint presentationMonitor;
93 gdouble imageScrollVOffset;
94 gdouble imageScrollHOffset;
95 gboolean imageScrollRestored;
99 gulong sigFileDownload;
100 gulong sigFilePreview;
103 gulong sigPrefsNotify;
105 GCancellable *monitorCancel;
106 GCancellable *taskCancel;
107 GCancellable *taskConfirm;
108 gboolean taskCapture;
109 gboolean taskPreview;
111 gboolean taskProcessEvents;
113 char *deleteImageDup;
119 typedef struct _EntangleCameraFileTaskData EntangleCameraFileTaskData;
120 struct _EntangleCameraFileTaskData {
121 EntangleCameraManager *manager;
122 EntangleCameraFile *file;
126 static void entangle_camera_progress_interface_init(gpointer g_iface,
127 gpointer iface_data);
128 static void entangle_camera_manager_window_interface_init(gpointer g_iface,
129 gpointer iface_data);
130 static void do_select_image(EntangleCameraManager *manager,
131 EntangleImage *image);
133 G_DEFINE_TYPE_EXTENDED(EntangleCameraManager, entangle_camera_manager, GTK_TYPE_WINDOW, 0,
134 G_IMPLEMENT_INTERFACE(ENTANGLE_TYPE_PROGRESS, entangle_camera_progress_interface_init)
135 G_IMPLEMENT_INTERFACE(ENTANGLE_TYPE_WINDOW, entangle_camera_manager_window_interface_init));
143 void do_menu_help_summary(GtkMenuItem *src,
144 EntangleCameraManager *manager);
145 void do_menu_help_manual(GtkMenuItem *src,
146 EntangleCameraManager *manager);
147 void do_menu_help_driver(GtkMenuItem *src,
148 EntangleCameraManager *manager);
149 void do_menu_help_supported(GtkMenuItem *src,
150 EntangleCameraManager *manager);
151 void do_menu_new_window(GtkImageMenuItem *src,
152 EntangleCameraManager *manager);
153 void do_menu_select_session(GtkImageMenuItem *src,
154 EntangleCameraManager *manager);
155 void do_menu_settings_toggled(GtkCheckMenuItem *src,
156 EntangleCameraManager *manager);
157 void do_menu_zoom_in(GtkImageMenuItem *src,
158 EntangleCameraManager *manager);
159 void do_menu_zoom_out(GtkImageMenuItem *src,
160 EntangleCameraManager *manager);
161 void do_menu_zoom_normal(GtkImageMenuItem *src,
162 EntangleCameraManager *manager);
163 void do_menu_zoom_best(GtkImageMenuItem *src,
164 EntangleCameraManager *manager);
165 void do_menu_fullscreen(GtkCheckMenuItem *src,
166 EntangleCameraManager *manager);
167 void do_menu_presentation(GtkCheckMenuItem *src,
168 EntangleCameraManager *manager);
169 void do_menu_preferences(GtkCheckMenuItem *src,
170 EntangleCameraManager *manager);
171 void do_toolbar_select_session(GtkFileChooserButton *src,
172 EntangleCameraManager *manager);
173 void do_toolbar_settings(GtkToggleToolButton *src,
174 EntangleCameraManager *manager);
175 void do_toolbar_cancel_clicked(GtkToolButton *src,
176 EntangleCameraManager *manager);
177 void do_toolbar_capture(GtkToolButton *src,
178 EntangleCameraManager *manager);
179 void do_toolbar_preview(GtkToggleToolButton *src,
180 EntangleCameraManager *manager);
181 void do_toolbar_zoom_in(GtkToolButton *src,
182 EntangleCameraManager *manager);
183 void do_toolbar_zoom_out(GtkToolButton *src,
184 EntangleCameraManager *manager);
185 void do_toolbar_zoom_normal(GtkToolButton *src,
186 EntangleCameraManager *manager);
187 void do_toolbar_zoom_best(GtkToolButton *src,
188 EntangleCameraManager *manager);
189 void do_toolbar_fullscreen(GtkToggleToolButton *src,
190 EntangleCameraManager *manager);
191 void do_menu_close(GtkMenuItem *src,
192 EntangleCameraManager *manager);
193 void do_menu_quit(GtkMenuItem *src,
194 EntangleCameraManager *manager);
195 void do_menu_help_about(GtkMenuItem *src,
196 EntangleCameraManager *manager);
197 void do_menu_connect(GtkMenuItem *src,
198 EntangleCameraManager *manager);
199 void do_menu_disconnect(GtkMenuItem *src,
200 EntangleCameraManager *manager);
201 void do_menu_capture(GtkMenuItem *src,
202 EntangleCameraManager *manager);
203 void do_menu_preview(GtkMenuItem *src,
204 EntangleCameraManager *manager);
205 void do_menu_cancel(GtkMenuItem *src,
206 EntangleCameraManager *manager);
207 gboolean do_manager_key_release(GtkWidget *widget G_GNUC_UNUSED,
210 void do_menu_session_open_activate(GtkMenuItem *item G_GNUC_UNUSED,
211 EntangleCameraManager *manager);
212 void do_menu_session_delete_activate(GtkMenuItem *item G_GNUC_UNUSED,
213 EntangleCameraManager *manager);
215 static EntanglePreferences *entangle_camera_manager_get_preferences(EntangleCameraManager *manager)
217 GtkApplication *gapp = gtk_window_get_application(GTK_WINDOW(manager));
218 EntangleApplication *app = ENTANGLE_APPLICATION(gapp);
219 return entangle_application_get_preferences(app);
222 static EntangleColourProfile *entangle_camera_manager_monitor_profile(GtkWindow *window)
225 GByteArray *profileData;
228 GdkAtom type = GDK_NONE;
232 EntangleColourProfile *profile = NULL;
234 gtk_widget_realize(GTK_WIDGET(window));
236 screen = gtk_widget_get_screen(GTK_WIDGET(window));
237 monitor = gdk_screen_get_monitor_at_window(screen,
238 gtk_widget_get_window(GTK_WIDGET(window)));
241 atom = g_strdup("_ICC_PROFILE");
243 atom = g_strdup_printf("_ICC_PROFILE_%d", monitor);
245 if (!gdk_property_get(gdk_screen_get_root_window(screen),
246 gdk_atom_intern(atom, FALSE),
248 0, 64 * 1024 * 1024, FALSE,
249 &type, &format, &nitems, &data) || nitems <= 0)
252 profileData = g_byte_array_new();
253 g_byte_array_append(profileData, data, nitems);
255 profile = entangle_colour_profile_new_data(profileData);
256 g_byte_array_unref(profileData);
266 static EntangleColourProfileTransform *entangle_camera_manager_colour_transform(EntangleCameraManager *manager)
268 g_return_val_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager), NULL);
270 EntangleColourProfileTransform *transform = NULL;
271 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
273 if (entangle_preferences_cms_get_enabled(prefs)) {
274 EntangleColourProfile *rgbProfile;
275 EntangleColourProfile *monitorProfile;
276 EntangleColourProfileIntent intent;
278 rgbProfile = entangle_preferences_cms_get_rgb_profile(prefs);
279 intent = entangle_preferences_cms_get_rendering_intent(prefs);
280 if (entangle_preferences_cms_get_detect_system_profile(prefs)) {
281 monitorProfile = entangle_camera_manager_monitor_profile(GTK_WINDOW(manager));
283 monitorProfile = entangle_preferences_cms_get_monitor_profile(prefs);
286 if (monitorProfile) {
287 transform = entangle_colour_profile_transform_new(rgbProfile, monitorProfile, intent);
288 g_object_unref(monitorProfile);
290 g_object_unref(rgbProfile);
297 static void entangle_camera_manager_update_colour_transform(EntangleCameraManager *manager)
299 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
301 EntangleCameraManagerPrivate *priv = manager->priv;
303 if (priv->colourTransform)
304 g_object_unref(priv->colourTransform);
306 priv->colourTransform = entangle_camera_manager_colour_transform(manager);
307 if (priv->imageLoader)
308 entangle_pixbuf_loader_set_colour_transform(ENTANGLE_PIXBUF_LOADER(priv->imageLoader),
309 priv->colourTransform);
310 if (priv->thumbLoader)
311 entangle_pixbuf_loader_set_colour_transform(ENTANGLE_PIXBUF_LOADER(priv->thumbLoader),
312 priv->colourTransform);
316 static void entangle_camera_manager_update_aspect_ratio(EntangleCameraManager *manager)
318 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
320 EntangleCameraManagerPrivate *priv = manager->priv;
321 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
322 const gchar *aspect = entangle_preferences_img_get_aspect_ratio(prefs);
325 entangle_image_display_set_aspect_ratio(priv->imageDisplay, 1.33);
329 d = g_ascii_strtod(aspect, &end);
330 if (end == aspect || (errno == ERANGE))
331 entangle_image_display_set_aspect_ratio(priv->imageDisplay, 1.33);
333 entangle_image_display_set_aspect_ratio(priv->imageDisplay, d);
338 static void entangle_camera_manager_update_mask_opacity(EntangleCameraManager *manager)
340 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
342 EntangleCameraManagerPrivate *priv = manager->priv;
343 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
344 gint opacity = entangle_preferences_img_get_mask_opacity(prefs);
346 entangle_image_display_set_mask_opacity(priv->imageDisplay, opacity / 100.0);
350 static void entangle_camera_manager_update_mask_enabled(EntangleCameraManager *manager)
352 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
354 EntangleCameraManagerPrivate *priv = manager->priv;
355 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
356 gboolean enabled = entangle_preferences_img_get_mask_enabled(prefs);
358 entangle_image_display_set_mask_enabled(priv->imageDisplay, enabled);
362 static void entangle_camera_manager_update_histogram_linear(EntangleCameraManager *manager)
364 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
366 EntangleCameraManagerPrivate *priv = manager->priv;
367 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
368 gboolean histogram_linear = entangle_preferences_interface_get_histogram_linear(prefs);
370 entangle_image_histogram_set_histogram_linear(priv->imageHistogram, histogram_linear);
374 static void do_presentation_monitor_toggled(GtkCheckMenuItem *menu, gpointer data)
376 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
378 EntangleCameraManager *manager = data;
379 EntangleCameraManagerPrivate *priv = manager->priv;
380 gpointer mon = g_object_get_data(G_OBJECT(menu), "monitor");
382 priv->presentationMonitor = GPOINTER_TO_INT(mon);
384 ENTANGLE_DEBUG("Set monitor %d", priv->presentationMonitor);
386 if (priv->imagePresentation)
387 entangle_image_popup_move_to_monitor(priv->imagePresentation,
388 priv->presentationMonitor);
392 static GtkWidget *entangle_camera_manager_monitor_menu(EntangleCameraManager *manager)
394 g_return_val_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager), NULL);
396 EntangleCameraManagerPrivate *priv = manager->priv;
397 GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(manager));
398 GtkWidget *menu = gtk_menu_new();
399 GSList *group = NULL;
400 #ifdef gdk_screen_get_primary_monitor
401 int active = gdk_screen_get_primary_monitor(screen);
406 for (int i = 0; i < gdk_screen_get_n_monitors(screen); i++) {
407 const gchar *name = gdk_screen_get_monitor_plug_name(screen, i);
408 GtkWidget *submenu = gtk_radio_menu_item_new_with_label(group, name);
409 g_object_set_data(G_OBJECT(submenu), "monitor", GINT_TO_POINTER(i));
410 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(submenu));
412 gtk_menu_shell_append(GTK_MENU_SHELL(menu), submenu);
415 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(submenu), TRUE);
417 g_signal_connect(submenu, "toggled",
418 G_CALLBACK(do_presentation_monitor_toggled), manager);
421 priv->presentationMonitor = active;
422 gtk_widget_show_all(menu);
428 static void entangle_camera_manager_update_viewfinder(EntangleCameraManager *manager)
430 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
432 EntangleCameraManagerPrivate *priv = manager->priv;
434 if (priv->taskPreview) {
435 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
436 gint gridLines = entangle_preferences_img_get_grid_lines(prefs);
437 gboolean focusPoint = entangle_preferences_img_get_focus_point(prefs);
439 entangle_image_display_set_focus_point(priv->imageDisplay, focusPoint);
440 entangle_image_display_set_grid_display(priv->imageDisplay, gridLines);
442 entangle_image_display_set_focus_point(priv->imageDisplay, FALSE);
443 entangle_image_display_set_grid_display(priv->imageDisplay,
444 ENTANGLE_IMAGE_DISPLAY_GRID_NONE);
449 static void entangle_camera_manager_update_image_loader(EntangleCameraManager *manager)
451 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
453 EntangleCameraManagerPrivate *priv = manager->priv;
455 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
456 gboolean embeddedPreview = entangle_preferences_img_get_embedded_preview(prefs);
457 entangle_image_loader_set_embedded_preview(priv->imageLoader, embeddedPreview);
461 static void entangle_camera_manager_prefs_changed(GObject *object G_GNUC_UNUSED,
465 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
467 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(data);
469 if (g_str_equal(spec->name, "interface-histogram-linear")) {
470 entangle_camera_manager_update_histogram_linear(manager);
471 } else if (g_str_equal(spec->name, "cms-enabled") ||
472 g_str_equal(spec->name, "cms-rgb-profile") ||
473 g_str_equal(spec->name, "cms-monitor-profile") ||
474 g_str_equal(spec->name, "cms-detect-system-profile") ||
475 g_str_equal(spec->name, "cms-rendering-intent")) {
476 entangle_camera_manager_update_colour_transform(manager);
477 } else if (g_str_equal(spec->name, "img-aspect-ratio")) {
478 entangle_camera_manager_update_aspect_ratio(manager);
479 } else if (g_str_equal(spec->name, "img-mask-opacity")) {
480 entangle_camera_manager_update_mask_opacity(manager);
481 } else if (g_str_equal(spec->name, "img-mask-enabled")) {
482 entangle_camera_manager_update_mask_enabled(manager);
483 } else if (g_str_equal(spec->name, "img-focus-point") ||
484 g_str_equal(spec->name, "img-grid-lines")) {
485 entangle_camera_manager_update_viewfinder(manager);
486 } else if (g_str_equal(spec->name, "img-embedded-preview")) {
487 entangle_camera_manager_update_image_loader(manager);
488 } else if (g_str_equal(spec->name, "img-onion-skin") ||
489 g_str_equal(spec->name, "img-onion-layers")) {
490 EntangleCameraManagerPrivate *priv = manager->priv;
491 do_select_image(manager, priv->currentImage);
496 static void do_capture_widget_sensitivity(EntangleCameraManager *manager)
498 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
500 EntangleCameraManagerPrivate *priv = manager->priv;
501 GtkWidget *toolCapture;
502 GtkWidget *toolPreview;
503 GtkWidget *toolCancel;
504 GtkWidget *menuCapture;
505 GtkWidget *menuPreview;
506 GtkWidget *menuCancel;
508 GtkWidget *toolSession;
509 GtkWidget *menuSession;
510 GtkWidget *menuConnect;
511 GtkWidget *menuDisconnect;
515 toolCapture = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-capture"));
516 toolPreview = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-preview"));
517 toolCancel = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-cancel"));
518 menuCapture = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-capture"));
519 menuPreview = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-preview"));
520 menuCancel = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-cancel"));
522 toolSession = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-session"));
523 menuSession = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-session"));
524 menuConnect = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-connect"));
525 menuDisconnect = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-disconnect"));
526 menuHelp = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-help-camera"));
529 gtk_widget_set_sensitive(toolCapture,
530 priv->cameraReady && !priv->taskCapture && priv->camera &&
531 entangle_camera_get_has_capture(priv->camera) ? TRUE : FALSE);
532 gtk_widget_set_sensitive(toolPreview,
533 priv->cameraReady && !priv->taskCapture && priv->camera &&
534 entangle_camera_get_has_capture(priv->camera) &&
535 entangle_camera_get_has_preview(priv->camera) &&
536 !priv->taskCapture ? TRUE : FALSE);
537 gtk_widget_set_sensitive(menuCapture,
538 priv->cameraReady && !priv->taskCapture && priv->camera &&
539 entangle_camera_get_has_capture(priv->camera) ? TRUE : FALSE);
540 gtk_widget_set_sensitive(menuPreview,
541 priv->cameraReady && !priv->taskCapture && priv->camera &&
542 entangle_camera_get_has_capture(priv->camera) &&
543 entangle_camera_get_has_preview(priv->camera) &&
544 !priv->taskCapture ? TRUE : FALSE);
546 gtk_widget_set_sensitive(toolSession,
548 gtk_widget_set_sensitive(menuSession,
550 gtk_widget_set_sensitive(menuConnect,
551 priv->camera ? FALSE : TRUE);
552 gtk_widget_set_sensitive(menuDisconnect,
553 priv->camera && priv->cameraReady ? TRUE : FALSE);
554 gtk_widget_set_sensitive(menuHelp,
555 priv->camera ? TRUE : FALSE);
557 gtk_widget_set_tooltip_text(toolCapture, _("Capture an image"));
558 gtk_widget_set_tooltip_text(toolPreview, _("Continuous capture preview"));
561 if (!entangle_camera_get_has_capture(priv->camera))
562 gtk_widget_set_tooltip_text(toolCapture, _("This camera does not support image capture"));
563 if (!entangle_camera_get_has_capture(priv->camera) ||
564 !entangle_camera_get_has_preview(priv->camera))
565 gtk_widget_set_tooltip_text(toolPreview, _("This camera does not support image preview"));
571 gtk_widget_show(settingsScroll);
572 gtk_widget_set_sensitive(settingsScroll, priv->cameraReady);
574 gtk_widget_hide(settingsScroll);
578 if (priv->taskCapture) {
579 gtk_widget_set_sensitive(toolCancel, True);
580 gtk_widget_set_sensitive(menuCancel, True);
582 gtk_widget_set_sensitive(toolCancel, False);
583 gtk_widget_set_sensitive(menuCancel, False);
586 entangle_camera_manager_update_viewfinder(manager);
590 static void do_restore_scroll(GtkWidget *widget,
591 GdkRectangle *allocation G_GNUC_UNUSED,
592 EntangleCameraManager *manager)
594 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
595 GtkAdjustment *hadjust;
596 GtkAdjustment *vadjust;
597 EntangleCameraManagerPrivate *priv = manager->priv;
599 if (!entangle_image_display_get_loaded(ENTANGLE_IMAGE_DISPLAY(widget)))
602 hadjust = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(priv->imageScroll));
603 vadjust = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(priv->imageScroll));
605 gtk_adjustment_set_value(hadjust,
606 priv->imageScrollHOffset);
607 gtk_adjustment_set_value(vadjust,
608 priv->imageScrollVOffset);
609 priv->imageScrollRestored = TRUE;
613 static void do_select_image(EntangleCameraManager *manager,
614 EntangleImage *image)
616 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
617 g_return_if_fail(!image || ENTANGLE_IS_IMAGE(image));
618 GList *newimages = NULL;
621 GtkAdjustment *hadjust;
622 GtkAdjustment *vadjust;
624 EntangleCameraManagerPrivate *priv = manager->priv;
625 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
627 ENTANGLE_DEBUG("Selected image %p %s", image,
628 image ? entangle_image_get_filename(image) : "<none>");
631 if (entangle_preferences_img_get_onion_skin(prefs))
632 newimages = entangle_session_browser_earlier_images
633 (priv->sessionBrowser,
634 entangle_image_get_filename(image) == NULL,
635 entangle_preferences_img_get_onion_layers(prefs));
637 newimages = g_list_prepend(newimages, g_object_ref(image));
640 /* Load all new images first */
643 EntangleImage *thisimage = tmp->data;
644 ENTANGLE_DEBUG("New image %p %s", thisimage,
645 entangle_image_get_filename(thisimage));
647 if (entangle_image_get_filename(thisimage))
648 entangle_pixbuf_loader_load(ENTANGLE_PIXBUF_LOADER(priv->imageLoader),
654 /* Now unload old images */
655 tmp = oldimages = entangle_image_display_get_image_list(priv->imageDisplay);
657 EntangleImage *thisimage = tmp->data;
659 ENTANGLE_DEBUG("Old %p %s", thisimage,
660 entangle_image_get_filename(thisimage));
662 if (entangle_image_get_filename(thisimage))
663 entangle_pixbuf_loader_unload(ENTANGLE_PIXBUF_LOADER(priv->imageLoader),
669 hadjust = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(priv->imageScroll));
670 vadjust = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(priv->imageScroll));
672 if (priv->imageScrollRestored) {
673 priv->imageScrollHOffset = gtk_adjustment_get_value(hadjust);
674 priv->imageScrollVOffset = gtk_adjustment_get_value(vadjust);
675 priv->imageScrollRestored = FALSE;
678 entangle_image_display_set_image_list(priv->imageDisplay, newimages);
682 if (priv->currentImage)
683 g_object_unref(priv->currentImage);
684 priv->currentImage = image;
686 entangle_image_statusbar_set_image(priv->imageStatusbar, priv->currentImage);
687 entangle_image_histogram_set_image(priv->imageHistogram, priv->currentImage);
688 if (priv->imagePresentation)
689 entangle_image_popup_set_image(priv->imagePresentation, priv->currentImage);
691 g_list_foreach(oldimages, (GFunc)g_object_unref, NULL);
692 g_list_free(oldimages);
693 g_list_foreach(newimages, (GFunc)g_object_unref, NULL);
694 g_list_free(newimages);
698 static void do_camera_task_error(EntangleCameraManager *manager,
699 const char *label, GError *error)
701 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
703 GtkWidget *msg = gtk_message_dialog_new(NULL,
707 _("Operation: %s"), label);
708 gtk_window_set_title(GTK_WINDOW(msg),
709 _("Entangle: Operation failed"));
710 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msg),
713 g_signal_connect_swapped(msg,
715 G_CALLBACK(gtk_widget_destroy),
717 gtk_widget_show_all(msg);
721 static void do_camera_process_events(EntangleCameraManager *manager);
724 static void do_camera_load_controls_refresh_finish(GObject *source,
725 GAsyncResult *result,
728 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
730 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(data);
731 EntangleCameraManagerPrivate *priv = manager->priv;
732 EntangleCamera *camera = ENTANGLE_CAMERA(source);
733 GError *error = NULL;
735 if (!entangle_camera_load_controls_finish(camera, result, &error)) {
736 GtkWidget *msg = gtk_message_dialog_new(NULL,
740 _("Camera load controls failed"));
741 gtk_window_set_title(GTK_WINDOW(msg),
742 _("Entangle: Camera load controls failed"));
743 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msg),
746 g_signal_connect_swapped(msg,
748 G_CALLBACK(gtk_widget_destroy),
750 gtk_widget_show_all(msg);
755 g_cancellable_reset(priv->monitorCancel);
757 do_camera_process_events(manager);
761 static void do_camera_process_events_finish(GObject *src,
762 GAsyncResult *result,
765 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
767 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(data);
768 EntangleCameraManagerPrivate *priv = manager->priv;
769 EntangleCamera *camera = ENTANGLE_CAMERA(src);
770 GError *error = NULL;
772 priv->taskProcessEvents = FALSE;
774 if (!entangle_camera_process_events_finish(camera,
777 if (g_cancellable_is_cancelled(priv->monitorCancel)) {
778 g_cancellable_reset(priv->monitorCancel);
780 do_camera_task_error(manager, _("Monitor"), error);
786 if (!priv->cameraReady) {
787 priv->cameraReady = TRUE;
788 do_capture_widget_sensitivity(manager);
794 if (priv->cameraChanged) {
795 priv->cameraChanged = FALSE;
796 entangle_camera_load_controls_async(priv->camera,
798 do_camera_load_controls_refresh_finish,
801 do_camera_process_events(manager);
806 static void do_camera_process_events(EntangleCameraManager *manager)
808 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
810 EntangleCameraManagerPrivate *priv = manager->priv;
815 if (priv->taskProcessEvents)
818 entangle_camera_process_events_async(priv->camera, 500, priv->monitorCancel,
819 do_camera_process_events_finish, manager);
821 priv->taskProcessEvents = TRUE;
824 static void do_camera_preview_image_finish(GObject *src,
829 static EntangleCameraFileTaskData *do_camera_task_begin(EntangleCameraManager *manager)
831 g_return_val_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager), NULL);
833 EntangleCameraManagerPrivate *priv = manager->priv;
834 EntangleCameraFileTaskData *data;
836 if (priv->taskActive)
839 data = g_new0(EntangleCameraFileTaskData, 1);
840 data->manager = g_object_ref(manager);
842 g_cancellable_cancel(priv->monitorCancel);
843 g_cancellable_reset(priv->taskConfirm);
844 g_cancellable_reset(priv->taskCancel);
845 priv->taskActive = TRUE;
847 g_free(priv->deleteImageDup);
848 priv->deleteImageDup = NULL;
854 static void do_camera_task_complete(EntangleCameraFileTaskData *data)
856 EntangleCameraManagerPrivate *priv = data->manager->priv;
857 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(data->manager);
861 g_object_unref(data->file);
865 if (priv->taskPreview &&
867 !g_cancellable_is_cancelled(priv->taskCancel) &&
868 entangle_preferences_capture_get_continuous_preview(prefs)) {
869 entangle_camera_preview_image_async(priv->camera,
871 do_camera_preview_image_finish,
875 preview = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-preview"));
876 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(preview), FALSE);
878 priv->taskActive = priv->taskPreview = priv->taskCapture = FALSE;
880 do_capture_widget_sensitivity(data->manager);
882 g_cancellable_reset(priv->taskConfirm);
883 g_cancellable_reset(priv->taskCancel);
884 g_cancellable_reset(priv->monitorCancel);
886 do_camera_process_events(data->manager);
887 g_object_unref(data->manager);
893 static void do_camera_file_download(EntangleCamera *cam G_GNUC_UNUSED, EntangleCameraFile *file, void *data)
895 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
897 EntangleCameraManager *manager = data;
898 EntangleCameraManagerPrivate *priv = manager->priv;
899 EntangleImage *image;
902 ENTANGLE_DEBUG("File download %p %p %p", cam, file, data);
904 localpath = entangle_session_next_filename(priv->session, file);
906 if (!entangle_camera_file_save_path(file, localpath, NULL)) {
907 ENTANGLE_DEBUG("Failed save path");
910 ENTANGLE_DEBUG("Saved to %s", localpath);
911 image = entangle_image_new_file(localpath);
913 entangle_session_add(priv->session, image);
914 do_select_image(manager, image);
916 g_object_unref(image);
923 static void do_camera_delete_file_finish(GObject *src,
927 EntangleCameraFileTaskData *data = opaque;
928 EntangleCamera *camera = ENTANGLE_CAMERA(src);
929 GError *error = NULL;
931 if (!entangle_camera_delete_file_finish(camera, res, &error)) {
932 do_camera_task_error(data->manager, _("Delete"), error);
934 /* Fallthrough to unref */
937 do_camera_task_complete(data);
941 static void do_camera_download_file_finish(GObject *src,
945 EntangleCameraFileTaskData *data = opaque;
946 EntangleCamera *camera = ENTANGLE_CAMERA(src);
947 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(data->manager);
948 GError *error = NULL;
950 if (!entangle_camera_download_file_finish(camera, res, &error)) {
951 do_camera_task_error(data->manager, _("Download"), error);
953 /* Fallthrough to delete anyway */
956 if (entangle_preferences_capture_get_delete_file(prefs)) {
957 entangle_camera_delete_file_async(camera,
960 do_camera_delete_file_finish,
963 do_camera_task_complete(data);
968 static void do_camera_capture_image_finish(GObject *src,
972 EntangleCameraFileTaskData *data = opaque;
973 EntangleCameraManagerPrivate *priv = data->manager->priv;
974 EntangleCamera *camera = ENTANGLE_CAMERA(src);
975 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(data->manager);
976 GError *error = NULL;
978 if (entangle_preferences_interface_get_screen_blank(prefs))
979 entangle_dpms_set_blanking(FALSE, NULL);
981 if (!(data->file = entangle_camera_capture_image_finish(camera, res, &error))) {
982 do_camera_task_error(data->manager, _("Capture"), error);
983 do_camera_task_complete(data);
988 if (g_cancellable_is_cancelled(priv->taskCancel)) {
989 if (entangle_preferences_capture_get_delete_file(prefs)) {
990 entangle_camera_delete_file_async(camera,
993 do_camera_delete_file_finish,
996 do_camera_task_complete(data);
999 entangle_camera_download_file_async(camera,
1002 do_camera_download_file_finish,
1008 static void do_camera_capture_image_discard_finish(GObject *src,
1012 EntangleCameraFileTaskData *data = opaque;
1013 EntangleCameraManagerPrivate *priv = data->manager->priv;
1014 EntangleCamera *camera = ENTANGLE_CAMERA(src);
1015 GError *error = NULL;
1019 if (!(data->file = entangle_camera_capture_image_finish(camera, res, &error))) {
1020 do_camera_task_error(data->manager, _("Capture"), error);
1021 do_camera_task_complete(data);
1022 g_error_free(error);
1026 filename = g_strdup(entangle_camera_file_get_name(data->file));
1027 if ((tmp = strrchr(filename, '.')))
1029 priv->deleteImageDup = filename;
1031 entangle_camera_delete_file_async(camera,
1034 do_camera_delete_file_finish,
1039 static void do_camera_set_viewfinder_finish(GObject *src,
1043 EntangleCameraFileTaskData *data = opaque;
1044 EntangleCamera *camera = ENTANGLE_CAMERA(src);
1045 GError *error = NULL;
1047 if (!entangle_camera_set_viewfinder_finish(camera, res, &error)) {
1048 do_camera_task_error(data->manager, _("Capture"), error);
1049 do_camera_task_complete(data);
1050 g_error_free(error);
1054 do_camera_task_complete(data);
1058 static void do_camera_preview_image_finish(GObject *src,
1062 EntangleCameraFileTaskData *data = opaque;
1063 EntangleCameraManagerPrivate *priv = data->manager->priv;
1064 EntangleCamera *camera = ENTANGLE_CAMERA(src);
1065 EntangleCameraFile *file;
1066 GError *error = NULL;
1068 if (!(file = entangle_camera_preview_image_finish(camera, res, &error))) {
1069 if (g_cancellable_is_cancelled(priv->taskCancel) && priv->camera) {
1070 if (entangle_camera_get_has_viewfinder(priv->camera))
1071 entangle_camera_set_viewfinder_async(priv->camera,
1074 do_camera_set_viewfinder_finish,
1077 entangle_camera_capture_image_async(priv->camera,
1079 do_camera_capture_image_discard_finish,
1082 priv->taskPreview = FALSE;
1083 do_camera_task_error(data->manager, _("Preview"), error);
1084 do_camera_task_complete(data);
1086 g_error_free(error);
1090 g_object_unref(file);
1092 if (g_cancellable_is_cancelled(priv->taskCancel)) {
1093 if (entangle_camera_get_has_viewfinder(priv->camera))
1094 entangle_camera_set_viewfinder_async(priv->camera,
1097 do_camera_set_viewfinder_finish,
1100 entangle_camera_capture_image_async(priv->camera,
1102 do_camera_capture_image_discard_finish,
1104 } else if (g_cancellable_is_cancelled(priv->taskConfirm)) {
1105 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(data->manager);
1107 if (entangle_preferences_interface_get_screen_blank(prefs))
1108 entangle_dpms_set_blanking(TRUE, NULL);
1110 g_cancellable_reset(priv->taskConfirm);
1111 entangle_camera_capture_image_async(priv->camera,
1113 do_camera_capture_image_finish,
1116 entangle_camera_preview_image_async(priv->camera,
1118 do_camera_preview_image_finish,
1124 static void do_camera_file_add(EntangleCamera *camera, EntangleCameraFile *file, void *opaque)
1126 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(opaque));
1127 g_return_if_fail(ENTANGLE_IS_CAMERA_FILE(file));
1129 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(opaque);
1130 EntangleCameraFileTaskData *data = g_new0(EntangleCameraFileTaskData, 1);
1131 EntangleCameraManagerPrivate *priv = manager->priv;
1133 ENTANGLE_DEBUG("File add %p %p %p", camera, file, data);
1135 data->manager = g_object_ref(manager);
1136 data->file = g_object_ref(file);
1138 if (priv->deleteImageDup) {
1139 gsize len = strlen(priv->deleteImageDup);
1140 if (strncmp(entangle_camera_file_get_name(file),
1141 priv->deleteImageDup,
1143 g_free(priv->deleteImageDup);
1144 priv->deleteImageDup = NULL;
1145 entangle_camera_delete_file_async(camera,
1148 do_camera_delete_file_finish,
1154 entangle_camera_download_file_async(camera,
1157 do_camera_download_file_finish,
1162 static void do_camera_file_preview(EntangleCamera *cam G_GNUC_UNUSED, EntangleCameraFile *file, void *data)
1164 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
1165 g_return_if_fail(ENTANGLE_IS_CAMERA_FILE(file));
1167 EntangleCameraManager *manager = data;
1168 EntangleCameraManagerPrivate *priv = manager->priv;
1172 EntangleImage *image;
1174 if (priv->taskPreview &&
1176 !g_cancellable_is_cancelled(priv->taskCancel)) {
1177 ENTANGLE_DEBUG("File preview %p %p %p", cam, file, data);
1179 bytes = entangle_camera_file_get_data(file);
1180 is = g_memory_input_stream_new_from_data(bytes->data, bytes->len, NULL);
1182 pixbuf = gdk_pixbuf_new_from_stream(is, NULL, NULL);
1184 image = entangle_image_new_pixbuf(pixbuf);
1186 do_select_image(manager, image);
1188 g_object_unref(pixbuf);
1190 g_object_unref(image);
1195 static void do_entangle_camera_progress_start(EntangleProgress *iface, float target, const char *msg)
1197 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(iface));
1199 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(iface);
1200 EntangleCameraManagerPrivate *priv = manager->priv;
1203 priv->taskTarget = target;
1204 mtr = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-progress"));
1206 gtk_widget_set_tooltip_text(mtr, msg);
1207 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(mtr), msg);
1208 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(mtr), 0);
1212 static void do_entangle_camera_progress_update(EntangleProgress *iface, float current)
1214 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(iface));
1216 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(iface);
1217 EntangleCameraManagerPrivate *priv = manager->priv;
1220 mtr = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-progress"));
1222 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(mtr), current / priv->taskTarget);
1226 static void do_entangle_camera_progress_stop(EntangleProgress *iface)
1228 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(iface));
1230 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(iface);
1231 EntangleCameraManagerPrivate *priv = manager->priv;
1234 mtr = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-progress"));
1236 gtk_widget_set_tooltip_text(mtr, "");
1237 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(mtr), "");
1238 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(mtr), 0);
1242 static void entangle_camera_progress_interface_init(gpointer g_iface,
1243 gpointer iface_data G_GNUC_UNUSED)
1245 EntangleProgressInterface *iface = g_iface;
1246 iface->start = do_entangle_camera_progress_start;
1247 iface->update = do_entangle_camera_progress_update;
1248 iface->stop = do_entangle_camera_progress_stop;
1252 static void do_entangle_camera_manager_set_builder(EntangleWindow *window,
1253 GtkBuilder *builder);
1255 static void entangle_camera_manager_window_interface_init(gpointer g_iface,
1256 gpointer iface_data G_GNUC_UNUSED)
1258 EntangleWindowInterface *iface = g_iface;
1259 iface->set_builder = do_entangle_camera_manager_set_builder;
1262 static void do_remove_camera(EntangleCameraManager *manager)
1264 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1266 EntangleCameraManagerPrivate *priv = manager->priv;
1269 g_cancellable_cancel(priv->monitorCancel);
1270 g_cancellable_cancel(priv->taskCancel);
1272 gtk_window_set_title(GTK_WINDOW(manager), _("Camera Manager - Entangle"));
1274 entangle_control_panel_set_camera(priv->controlPanel, NULL);
1275 entangle_camera_set_progress(priv->camera, NULL);
1277 g_signal_handler_disconnect(priv->camera, priv->sigFilePreview);
1278 g_signal_handler_disconnect(priv->camera, priv->sigFileDownload);
1279 g_signal_handler_disconnect(priv->camera, priv->sigFileAdd);
1281 if (priv->imagePresentation) {
1282 gtk_widget_hide(GTK_WIDGET(priv->imagePresentation));
1283 g_object_unref(priv->imagePresentation);
1284 priv->imagePresentation = NULL;
1287 mtr = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-progress"));
1288 gtk_widget_set_tooltip_text(mtr, "");
1289 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(mtr), "");
1290 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(mtr), 0);
1294 static void do_camera_load_controls_finish(GObject *source,
1295 GAsyncResult *result,
1298 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
1300 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(data);
1301 EntangleCameraManagerPrivate *priv = manager->priv;
1303 EntangleCamera *cam = ENTANGLE_CAMERA(source);
1304 GError *error = NULL;
1306 if (entangle_camera_load_controls_finish(cam, result, &error)) {
1307 do_capture_widget_sensitivity(manager);
1308 entangle_control_panel_set_camera(priv->controlPanel, priv->camera);
1310 GtkWidget *msg = gtk_message_dialog_new(NULL,
1314 _("Camera load controls failed"));
1315 gtk_window_set_title(GTK_WINDOW(msg),
1316 _("Entangle: Camera load controls failed"));
1317 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msg),
1320 g_signal_connect_swapped(msg,
1322 G_CALLBACK(gtk_widget_destroy),
1324 gtk_widget_show_all(msg);
1326 g_error_free(error);
1329 g_cancellable_reset(priv->monitorCancel);
1330 do_camera_process_events(manager);
1334 static void do_camera_connect_finish(GObject *source,
1335 GAsyncResult *result,
1338 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
1340 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(data);
1341 EntangleCameraManagerPrivate *priv = manager->priv;
1342 EntangleCamera *cam = ENTANGLE_CAMERA(source);
1343 GError *error = NULL;
1345 if (entangle_camera_connect_finish(cam, result, &error)) {
1346 entangle_camera_load_controls_async(priv->camera,
1348 do_camera_load_controls_finish,
1352 GtkWidget *msg = gtk_message_dialog_new(NULL,
1356 _("Unable to connect to camera: %s"),
1359 gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(msg),
1361 _("Check that the camera is not\n\n"
1362 " - opened by another photo <b>application</b>\n"
1363 " - mounted as a <b>filesystem</b> on the desktop\n"
1364 " - in <b>sleep mode</b> to save battery power\n"));
1366 gtk_dialog_add_button(GTK_DIALOG(msg), _("Cancel"), GTK_RESPONSE_CANCEL);
1367 gtk_dialog_add_button(GTK_DIALOG(msg), _("Retry"), GTK_RESPONSE_ACCEPT);
1368 gtk_dialog_set_default_response(GTK_DIALOG(msg), GTK_RESPONSE_ACCEPT);
1369 response = gtk_dialog_run(GTK_DIALOG(msg));
1371 gtk_widget_destroy(msg);
1373 if (response == GTK_RESPONSE_CANCEL) {
1374 entangle_camera_manager_set_camera(manager, NULL);
1376 entangle_camera_connect_async(cam,
1378 do_camera_connect_finish,
1381 g_error_free(error);
1386 static gboolean need_camera_unmount(EntangleCamera *cam)
1388 g_return_val_if_fail(ENTANGLE_IS_CAMERA(cam), FALSE);
1390 if (entangle_camera_is_mounted(cam)) {
1392 GtkWidget *msg = gtk_message_dialog_new(NULL,
1397 _("Camera is in use"));
1399 gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(msg),
1401 _("The camera cannot be opened because it is "
1402 "currently mounted as a filesystem. Do you "
1403 "wish to umount it now ?"));
1405 gtk_dialog_add_button(GTK_DIALOG(msg), _("No"), GTK_RESPONSE_NO);
1406 gtk_dialog_add_button(GTK_DIALOG(msg), _("Yes"), GTK_RESPONSE_YES);
1407 gtk_dialog_set_default_response(GTK_DIALOG(msg), GTK_RESPONSE_YES);
1409 response = gtk_dialog_run(GTK_DIALOG(msg));
1411 gtk_widget_destroy(msg);
1413 if (response == GTK_RESPONSE_YES)
1420 static void do_camera_unmount_finish(GObject *source,
1421 GAsyncResult *result,
1424 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
1426 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(data);
1427 EntangleCameraManagerPrivate *priv = manager->priv;
1428 EntangleCamera *cam = ENTANGLE_CAMERA(source);
1429 GError *error = NULL;
1431 if (entangle_camera_unmount_finish(cam, result, &error)) {
1432 entangle_camera_connect_async(priv->camera,
1434 do_camera_connect_finish,
1437 GtkWidget *msg = gtk_message_dialog_new(NULL,
1441 _("Camera connect failed"));
1442 gtk_window_set_title(GTK_WINDOW(msg),
1443 _("Entangle: Camera connect failed"));
1444 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msg),
1447 g_signal_connect_swapped(msg,
1449 G_CALLBACK(gtk_widget_destroy),
1451 gtk_widget_show_all(msg);
1452 entangle_camera_manager_set_camera(manager, NULL);
1454 g_error_free(error);
1459 static void do_camera_control_changed(EntangleCamera *cam G_GNUC_UNUSED,
1462 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
1464 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(data);
1465 EntangleCameraManagerPrivate *priv = manager->priv;
1467 priv->cameraChanged = TRUE;
1471 static void do_add_camera(EntangleCameraManager *manager)
1473 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1475 EntangleCameraManagerPrivate *priv = manager->priv;
1478 title = g_strdup_printf(_("%s Camera Manager - Entangle"),
1479 entangle_camera_get_model(priv->camera));
1481 gtk_window_set_title(GTK_WINDOW(manager), title);
1484 priv->sigFilePreview = g_signal_connect(priv->camera, "camera-file-previewed",
1485 G_CALLBACK(do_camera_file_preview), manager);
1486 priv->sigFileDownload = g_signal_connect(priv->camera, "camera-file-downloaded",
1487 G_CALLBACK(do_camera_file_download), manager);
1488 priv->sigFileAdd = g_signal_connect(priv->camera, "camera-file-added",
1489 G_CALLBACK(do_camera_file_add), manager);
1490 priv->sigChanged = g_signal_connect(priv->camera, "camera-controls-changed",
1491 G_CALLBACK(do_camera_control_changed), manager);
1493 entangle_camera_set_progress(priv->camera, ENTANGLE_PROGRESS(manager));
1495 if (need_camera_unmount(priv->camera)) {
1496 entangle_camera_unmount_async(priv->camera,
1498 do_camera_unmount_finish,
1501 entangle_camera_connect_async(priv->camera,
1503 do_camera_connect_finish,
1509 static void entangle_camera_manager_get_property(GObject *object,
1514 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(object);
1515 EntangleCameraManagerPrivate *priv = manager->priv;
1520 g_value_set_object(value, priv->camera);
1524 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1529 static void do_camera_removed(EntangleCameraList *cameras G_GNUC_UNUSED,
1530 EntangleCamera *camera,
1533 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
1535 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(data);
1536 EntangleCameraManagerPrivate *priv = manager->priv;
1538 if (priv->camera == camera)
1539 entangle_camera_manager_set_camera(manager, NULL);
1543 static void do_entangle_camera_manager_set_app(GObject *object,
1544 GParamSpec *spec G_GNUC_UNUSED)
1546 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(object));
1548 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(object);
1549 EntangleCameraManagerPrivate *priv = manager->priv;
1550 EntanglePreferences *prefs;
1551 EntangleCameraList *cameras;
1555 EntangleApplication *app;
1557 app = ENTANGLE_APPLICATION(gtk_window_get_application(GTK_WINDOW(manager)));
1559 prefs = entangle_application_get_preferences(app);
1560 priv->sigPrefsNotify = g_signal_connect(prefs,
1562 G_CALLBACK(entangle_camera_manager_prefs_changed),
1564 cameras = entangle_application_get_cameras(app);
1565 g_signal_connect(cameras, "camera-removed", G_CALLBACK(do_camera_removed), manager);
1566 directory = entangle_preferences_capture_get_last_session(prefs);
1567 pattern = entangle_preferences_capture_get_filename_pattern(prefs);
1569 entangle_camera_manager_update_histogram_linear(manager);
1570 entangle_camera_manager_update_colour_transform(manager);
1571 entangle_camera_manager_update_aspect_ratio(manager);
1572 entangle_camera_manager_update_mask_opacity(manager);
1573 entangle_camera_manager_update_mask_enabled(manager);
1574 entangle_camera_manager_update_image_loader(manager);
1576 priv->session = entangle_session_new(directory, pattern);
1578 chooser = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-session-button"));
1579 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser), directory);
1581 entangle_session_load(priv->session);
1582 entangle_session_browser_set_session(priv->sessionBrowser, priv->session);
1588 static void entangle_camera_manager_set_property(GObject *object,
1590 const GValue *value,
1593 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(object);
1595 ENTANGLE_DEBUG("Set prop %d", prop_id);
1600 entangle_camera_manager_set_camera(manager, g_value_get_object(value));
1604 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1610 static void entangle_camera_manager_finalize(GObject *object)
1612 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(object);
1613 EntangleCameraManagerPrivate *priv = manager->priv;
1615 ENTANGLE_DEBUG("Finalize manager");
1617 g_free(priv->deleteImageDup);
1619 g_object_unref(priv->monitorCancel);
1620 g_object_unref(priv->taskCancel);
1621 g_object_unref(priv->taskConfirm);
1623 if (priv->imageLoader)
1624 g_object_unref(priv->imageLoader);
1625 if (priv->thumbLoader)
1626 g_object_unref(priv->thumbLoader);
1627 if (priv->colourTransform)
1628 g_object_unref(priv->colourTransform);
1630 g_object_unref(priv->camera);
1631 if (priv->prefsDisplay)
1632 g_object_unref(priv->prefsDisplay);
1634 g_object_unref(priv->picker);
1636 if (priv->imagePresentation)
1637 g_object_unref(priv->imagePresentation);
1640 g_object_unref(priv->builder);
1642 g_hash_table_destroy(priv->popups);
1644 G_OBJECT_CLASS(entangle_camera_manager_parent_class)->finalize(object);
1648 static void entangle_camera_manager_class_init(EntangleCameraManagerClass *klass)
1650 GObjectClass *object_class = G_OBJECT_CLASS(klass);
1652 object_class->finalize = entangle_camera_manager_finalize;
1653 object_class->get_property = entangle_camera_manager_get_property;
1654 object_class->set_property = entangle_camera_manager_set_property;
1656 g_signal_new("closed",
1657 G_TYPE_FROM_CLASS(klass),
1659 G_STRUCT_OFFSET(EntangleCameraManagerClass, manager_connect),
1661 g_cclosure_marshal_VOID__VOID,
1665 g_object_class_install_property(object_class,
1667 g_param_spec_object("camera",
1669 "Camera to be managed",
1670 ENTANGLE_TYPE_CAMERA,
1672 G_PARAM_STATIC_NAME |
1673 G_PARAM_STATIC_NICK |
1674 G_PARAM_STATIC_BLURB));
1676 g_type_class_add_private(klass, sizeof(EntangleCameraManagerPrivate));
1680 void do_menu_help_summary(GtkMenuItem *src G_GNUC_UNUSED,
1681 EntangleCameraManager *manager)
1683 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1685 EntangleCameraManagerPrivate *priv = manager->priv;
1687 if (!priv->summary) {
1688 priv->summary = entangle_camera_info_new();
1689 entangle_camera_info_set_camera(priv->summary, priv->camera);
1690 entangle_camera_info_set_data(priv->summary, ENTANGLE_CAMERA_INFO_DATA_SUMMARY);
1691 gtk_window_set_transient_for(GTK_WINDOW(priv->summary),
1692 GTK_WINDOW(manager));
1695 gtk_widget_show(GTK_WIDGET(priv->summary));
1698 void do_menu_help_manual(GtkMenuItem *src G_GNUC_UNUSED,
1699 EntangleCameraManager *manager)
1701 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1703 EntangleCameraManagerPrivate *priv = manager->priv;
1705 if (!priv->manual) {
1706 priv->manual = entangle_camera_info_new();
1707 entangle_camera_info_set_camera(priv->manual, priv->camera);
1708 entangle_camera_info_set_data(priv->manual, ENTANGLE_CAMERA_INFO_DATA_MANUAL);
1709 gtk_window_set_transient_for(GTK_WINDOW(priv->manual),
1710 GTK_WINDOW(manager));
1713 gtk_widget_show(GTK_WIDGET(priv->manual));
1716 void do_menu_help_driver(GtkMenuItem *src G_GNUC_UNUSED,
1717 EntangleCameraManager *manager)
1719 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1721 EntangleCameraManagerPrivate *priv = manager->priv;
1723 if (!priv->driver) {
1724 priv->driver = entangle_camera_info_new();
1725 entangle_camera_info_set_camera(priv->driver, priv->camera);
1726 entangle_camera_info_set_data(priv->driver, ENTANGLE_CAMERA_INFO_DATA_DRIVER);
1727 gtk_window_set_transient_for(GTK_WINDOW(priv->driver),
1728 GTK_WINDOW(manager));
1731 gtk_widget_show(GTK_WIDGET(priv->driver));
1734 void do_menu_help_supported(GtkMenuItem *src G_GNUC_UNUSED,
1735 EntangleCameraManager *manager)
1737 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1739 EntangleCameraManagerPrivate *priv = manager->priv;
1741 if (!priv->supported) {
1742 EntangleApplication *app = ENTANGLE_APPLICATION(gtk_window_get_application(GTK_WINDOW(manager)));
1743 priv->supported = entangle_camera_support_new();
1744 entangle_camera_support_set_camera_list(priv->supported, entangle_application_get_cameras(app));
1745 gtk_window_set_transient_for(GTK_WINDOW(priv->supported),
1746 GTK_WINDOW(manager));
1749 gtk_widget_show(GTK_WIDGET(priv->supported));
1753 void do_menu_new_window(GtkImageMenuItem *src G_GNUC_UNUSED,
1754 EntangleCameraManager *manager)
1756 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1758 GtkApplication *app = gtk_window_get_application(GTK_WINDOW(manager));
1759 EntangleCameraManager *newmanager = entangle_camera_manager_new();
1760 gtk_window_set_application(GTK_WINDOW(newmanager), app);
1762 gtk_widget_show(GTK_WIDGET(newmanager));
1763 gtk_window_present(GTK_WINDOW(newmanager));
1767 void do_toolbar_select_session(GtkFileChooserButton *src,
1768 EntangleCameraManager *manager)
1770 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1772 EntangleCameraManagerPrivate *priv = manager->priv;
1773 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
1774 EntangleSession *session;
1778 do_select_image(manager, NULL);
1779 dir = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(src));
1780 pattern = entangle_preferences_capture_get_filename_pattern(prefs);
1781 session = entangle_session_new(dir, pattern);
1782 entangle_preferences_capture_set_last_session(prefs, dir);
1785 entangle_session_load(session);
1787 g_object_unref(priv->session);
1788 priv->session = session;
1789 entangle_session_browser_set_session(priv->sessionBrowser, session);
1790 g_hash_table_remove_all(priv->popups);
1791 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(src), dir);
1795 void do_menu_select_session(GtkImageMenuItem *src G_GNUC_UNUSED,
1796 EntangleCameraManager *manager)
1798 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1800 EntangleCameraManagerPrivate *priv = manager->priv;
1803 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
1805 chooser = gtk_file_chooser_dialog_new(_("Select a folder"),
1806 GTK_WINDOW(manager),
1807 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
1809 GTK_RESPONSE_REJECT,
1811 GTK_RESPONSE_ACCEPT,
1813 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(chooser), TRUE);
1814 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(chooser), FALSE);
1816 dir = entangle_preferences_capture_get_last_session(prefs);
1817 g_mkdir_with_parents(dir, 0777);
1819 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser), dir);
1822 gtk_widget_hide(chooser);
1824 if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_ACCEPT) {
1825 GtkWidget *toolchooser = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-session-button"));
1826 EntangleSession *session;
1828 do_select_image(manager, NULL);
1829 dir = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser));
1830 pattern = entangle_preferences_capture_get_filename_pattern(prefs);
1831 session = entangle_session_new(dir, pattern);
1832 entangle_preferences_capture_set_last_session(prefs, dir);
1835 entangle_session_load(session);
1837 g_object_unref(priv->session);
1838 priv->session = session;
1839 entangle_session_browser_set_session(priv->sessionBrowser, session);
1840 g_hash_table_remove_all(priv->popups);
1841 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(toolchooser), dir);
1844 gtk_widget_destroy(chooser);
1848 void do_menu_settings_toggled(GtkCheckMenuItem *src,
1849 EntangleCameraManager *manager)
1851 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1853 EntangleCameraManagerPrivate *priv = manager->priv;
1854 GtkWidget *settings;
1858 settings = GTK_WIDGET(gtk_builder_get_object(priv->builder, "settings-box"));
1859 toolbar = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-settings"));
1861 active = gtk_check_menu_item_get_active(src);
1862 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(toolbar), active);
1865 gtk_widget_show(settings);
1867 gtk_widget_hide(settings);
1871 void do_toolbar_settings(GtkToggleToolButton *src,
1872 EntangleCameraManager *manager)
1874 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1876 EntangleCameraManagerPrivate *priv = manager->priv;
1877 GtkWidget *settings;
1881 settings = GTK_WIDGET(gtk_builder_get_object(priv->builder, "settings-box"));
1882 menu = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-settings"));
1884 active = gtk_toggle_tool_button_get_active(src);
1885 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), active);
1888 gtk_widget_show(settings);
1890 gtk_widget_hide(settings);
1894 void do_toolbar_cancel_clicked(GtkToolButton *src G_GNUC_UNUSED,
1895 EntangleCameraManager *manager)
1897 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1899 EntangleCameraManagerPrivate *priv = manager->priv;
1901 if (priv->taskCancel)
1902 g_cancellable_cancel(priv->taskCancel);
1906 static void do_camera_manager_capture(EntangleCameraManager *manager)
1908 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1910 EntangleCameraManagerPrivate *priv = manager->priv;
1911 GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM(gtk_builder_get_object(priv->builder, "menu-sync-windows"));
1913 if (gtk_check_menu_item_get_active(item)) {
1914 GtkApplication *app = gtk_window_get_application(GTK_WINDOW(manager));
1915 GList *windows = gtk_application_get_windows(app);
1918 GtkWindow *window = windows->data;
1920 if (ENTANGLE_IS_CAMERA_MANAGER(window))
1921 entangle_camera_manager_capture(ENTANGLE_CAMERA_MANAGER(window));
1923 windows = windows->next;
1926 entangle_camera_manager_capture(manager);
1931 static void do_camera_manager_preview_begin(EntangleCameraManager *manager)
1933 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1935 EntangleCameraManagerPrivate *priv = manager->priv;
1936 GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM(gtk_builder_get_object(priv->builder, "menu-sync-windows"));
1938 if (gtk_check_menu_item_get_active(item)) {
1939 GtkApplication *app = gtk_window_get_application(GTK_WINDOW(manager));
1940 GList *windows = gtk_application_get_windows(app);
1943 GtkWindow *window = windows->data;
1944 if (ENTANGLE_IS_CAMERA_MANAGER(window))
1945 entangle_camera_manager_preview_begin(ENTANGLE_CAMERA_MANAGER(window));
1947 windows = windows->next;
1950 entangle_camera_manager_preview_begin(manager);
1955 static void do_camera_manager_preview_cancel(EntangleCameraManager *manager)
1957 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1959 EntangleCameraManagerPrivate *priv = manager->priv;
1960 GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM(gtk_builder_get_object(priv->builder, "menu-sync-windows"));
1962 if (gtk_check_menu_item_get_active(item)) {
1963 GtkApplication *app = gtk_window_get_application(GTK_WINDOW(manager));
1964 GList *windows = gtk_application_get_windows(app);
1967 GtkWindow *window = windows->data;
1968 if (ENTANGLE_IS_CAMERA_MANAGER(window))
1969 entangle_camera_manager_preview_cancel(ENTANGLE_CAMERA_MANAGER(window));
1971 windows = windows->next;
1974 entangle_camera_manager_preview_cancel(manager);
1979 void entangle_camera_manager_capture(EntangleCameraManager *manager)
1981 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
1983 EntangleCameraManagerPrivate *priv = manager->priv;
1984 ENTANGLE_DEBUG("starting capture operation");
1989 if (priv->taskPreview) {
1990 g_cancellable_cancel(priv->taskConfirm);
1992 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
1993 EntangleCameraFileTaskData *data;
1994 if (!(data = do_camera_task_begin(manager)))
1997 priv->taskCapture = TRUE;
1998 do_capture_widget_sensitivity(manager);
2000 if (entangle_preferences_interface_get_screen_blank(prefs))
2001 entangle_dpms_set_blanking(TRUE, NULL);
2003 entangle_camera_capture_image_async(priv->camera,
2005 do_camera_capture_image_finish,
2011 void entangle_camera_manager_preview_begin(EntangleCameraManager *manager)
2013 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2015 EntangleCameraManagerPrivate *priv = manager->priv;
2016 EntangleCameraFileTaskData *data;
2021 ENTANGLE_DEBUG("starting preview operation");
2022 if (!(data = do_camera_task_begin(manager)))
2025 priv->taskPreview = TRUE;
2026 do_capture_widget_sensitivity(manager);
2027 entangle_camera_preview_image_async(priv->camera,
2029 do_camera_preview_image_finish,
2034 void entangle_camera_manager_preview_cancel(EntangleCameraManager *manager)
2036 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2038 EntangleCameraManagerPrivate *priv = manager->priv;
2044 if (priv->taskPreview) {
2045 ENTANGLE_DEBUG("Cancelling capture operation");
2046 g_cancellable_cancel(priv->taskCancel);
2048 img = entangle_session_browser_selected_image(priv->sessionBrowser);
2050 do_select_image(manager, img);
2051 g_object_unref(img);
2057 void do_toolbar_capture(GtkToolButton *src G_GNUC_UNUSED,
2058 EntangleCameraManager *manager)
2060 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2062 do_camera_manager_capture(manager);
2066 void do_toolbar_preview(GtkToggleToolButton *src,
2067 EntangleCameraManager *manager)
2069 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2071 EntangleCameraManagerPrivate *priv = manager->priv;
2072 GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM(gtk_builder_get_object(priv->builder, "menu-preview"));
2074 if (gtk_toggle_tool_button_get_active(src)) {
2075 if (!gtk_check_menu_item_get_active(item)) {
2076 gtk_check_menu_item_set_active(item, True);
2077 do_camera_manager_preview_begin(manager);
2080 if (gtk_check_menu_item_get_active(item)) {
2081 gtk_check_menu_item_set_active(item, False);
2082 do_camera_manager_preview_cancel(manager);
2088 void do_menu_capture(GtkMenuItem *src G_GNUC_UNUSED,
2089 EntangleCameraManager *manager)
2091 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2093 do_camera_manager_capture(manager);
2097 void do_menu_preview(GtkMenuItem *src,
2098 EntangleCameraManager *manager)
2100 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2102 EntangleCameraManagerPrivate *priv = manager->priv;
2103 GtkToggleToolButton *button = GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(priv->builder, "toolbar-preview"));
2105 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(src))) {
2106 if (!gtk_toggle_tool_button_get_active(button)) {
2107 gtk_toggle_tool_button_set_active(button, True);
2108 do_camera_manager_preview_begin(manager);
2111 if (gtk_toggle_tool_button_get_active(button)) {
2112 gtk_toggle_tool_button_set_active(button, False);
2113 do_camera_manager_preview_cancel(manager);
2119 void do_menu_cancel(GtkMenuItem *src G_GNUC_UNUSED,
2120 EntangleCameraManager *manager)
2122 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2124 EntangleCameraManagerPrivate *priv = manager->priv;
2126 if (priv->taskCancel)
2127 g_cancellable_cancel(priv->taskCancel);
2131 static void do_camera_autofocus_finish(GObject *source,
2132 GAsyncResult *result,
2135 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
2137 EntangleCamera *camera = ENTANGLE_CAMERA(source);
2138 GError *error = NULL;
2140 if (!entangle_camera_autofocus_finish(camera, result, &error)) {
2141 GtkWidget *msg = gtk_message_dialog_new(NULL,
2145 _("Autofocus failed"));
2146 gtk_window_set_title(GTK_WINDOW(msg),
2147 _("Entangle: Camera autofocus failed"));
2148 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msg),
2151 g_signal_connect_swapped(msg,
2153 G_CALLBACK(gtk_widget_destroy),
2155 gtk_widget_show_all(msg);
2157 g_error_free(error);
2162 static void do_camera_manualfocus_finish(GObject *source,
2163 GAsyncResult *result,
2166 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
2168 EntangleCamera *camera = ENTANGLE_CAMERA(source);
2169 GError *error = NULL;
2171 if (!entangle_camera_manualfocus_finish(camera, result, &error)) {
2172 GtkWidget *msg = gtk_message_dialog_new(NULL,
2176 _("Manual focus failed"));
2177 gtk_window_set_title(GTK_WINDOW(msg),
2178 _("Entangle: Camera manual focus failed"));
2179 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msg),
2182 g_signal_connect_swapped(msg,
2184 G_CALLBACK(gtk_widget_destroy),
2186 gtk_widget_show_all(msg);
2188 g_error_free(error);
2193 gboolean do_manager_key_release(GtkWidget *widget G_GNUC_UNUSED,
2197 g_return_val_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data), FALSE);
2199 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(data);
2200 EntangleCameraManagerPrivate *priv = manager->priv;
2202 switch (ev->keyval) {
2204 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
2205 gboolean enabled = entangle_preferences_img_get_mask_enabled(prefs);
2206 entangle_preferences_img_set_mask_enabled(prefs, !enabled);
2210 EntanglePreferences *prefs = entangle_camera_manager_get_preferences(manager);
2211 gboolean linear = entangle_preferences_interface_get_histogram_linear(prefs);
2212 entangle_preferences_interface_set_histogram_linear(prefs, !linear);
2216 if (priv->taskPreview) {
2217 entangle_camera_autofocus_async(priv->camera,
2219 do_camera_autofocus_finish,
2224 case GDK_KEY_comma: {
2225 if (priv->taskPreview) {
2226 entangle_camera_manualfocus_async(priv->camera,
2229 do_camera_manualfocus_finish,
2234 case GDK_KEY_period: {
2235 if (priv->taskPreview) {
2236 entangle_camera_manualfocus_async(priv->camera,
2239 do_camera_manualfocus_finish,
2244 case GDK_KEY_less: {
2245 if (priv->taskPreview) {
2246 entangle_camera_manualfocus_async(priv->camera,
2249 do_camera_manualfocus_finish,
2254 case GDK_KEY_greater: {
2255 if (priv->taskPreview) {
2256 entangle_camera_manualfocus_async(priv->camera,
2259 do_camera_manualfocus_finish,
2272 static void do_zoom_widget_sensitivity(EntangleCameraManager *manager)
2274 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2276 EntangleCameraManagerPrivate *priv = manager->priv;
2277 GtkWidget *toolzoomnormal = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-zoom-normal"));
2278 GtkWidget *toolzoombest = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-zoom-best"));
2279 GtkWidget *toolzoomin = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-zoom-in"));
2280 GtkWidget *toolzoomout = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-zoom-out"));
2282 GtkWidget *menuzoomnormal = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-zoom-normal"));
2283 GtkWidget *menuzoombest = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-zoom-best"));
2284 GtkWidget *menuzoomin = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-zoom-in"));
2285 GtkWidget *menuzoomout = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-zoom-out"));
2288 autoscale = entangle_image_display_get_autoscale(priv->imageDisplay);
2291 gtk_widget_set_sensitive(toolzoombest, FALSE);
2292 gtk_widget_set_sensitive(toolzoomnormal, TRUE);
2293 gtk_widget_set_sensitive(toolzoomin, FALSE);
2294 gtk_widget_set_sensitive(toolzoomout, FALSE);
2296 gtk_widget_set_sensitive(menuzoombest, FALSE);
2297 gtk_widget_set_sensitive(menuzoomnormal, TRUE);
2298 gtk_widget_set_sensitive(menuzoomin, FALSE);
2299 gtk_widget_set_sensitive(menuzoomout, FALSE);
2301 gtk_widget_set_sensitive(toolzoombest, TRUE);
2302 gtk_widget_set_sensitive(toolzoomnormal, priv->zoomLevel == 0 ? FALSE : TRUE);
2303 gtk_widget_set_sensitive(toolzoomin, priv->zoomLevel == 10 ? FALSE : TRUE);
2304 gtk_widget_set_sensitive(toolzoomout, priv->zoomLevel == -10 ? FALSE : TRUE);
2306 gtk_widget_set_sensitive(menuzoombest, TRUE);
2307 gtk_widget_set_sensitive(menuzoomnormal, priv->zoomLevel == 0 ? FALSE : TRUE);
2308 gtk_widget_set_sensitive(menuzoomin, priv->zoomLevel == 10 ? FALSE : TRUE);
2309 gtk_widget_set_sensitive(menuzoomout, priv->zoomLevel == -10 ? FALSE : TRUE);
2314 static void entangle_camera_manager_update_zoom(EntangleCameraManager *manager)
2316 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2318 EntangleCameraManagerPrivate *priv = manager->priv;
2320 if (priv->zoomLevel > 0)
2321 entangle_image_display_set_scale(priv->imageDisplay, 1.0+priv->zoomLevel);
2322 else if (priv->zoomLevel < 0)
2323 entangle_image_display_set_scale(priv->imageDisplay, 1.0/pow(1.5, -priv->zoomLevel));
2325 entangle_image_display_set_scale(priv->imageDisplay, 0.0);
2326 do_zoom_widget_sensitivity(manager);
2330 static void entangle_camera_manager_zoom_in(EntangleCameraManager *manager)
2332 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2334 EntangleCameraManagerPrivate *priv = manager->priv;
2336 if (priv->zoomLevel < 10)
2337 priv->zoomLevel += 1;
2339 entangle_camera_manager_update_zoom(manager);
2343 static void entangle_camera_manager_zoom_out(EntangleCameraManager *manager)
2345 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2347 EntangleCameraManagerPrivate *priv = manager->priv;
2349 if (priv->zoomLevel > -10)
2350 priv->zoomLevel -= 1;
2352 entangle_camera_manager_update_zoom(manager);
2355 static void entangle_camera_manager_zoom_normal(EntangleCameraManager *manager)
2357 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2359 EntangleCameraManagerPrivate *priv = manager->priv;
2361 priv->zoomLevel = 0;
2362 entangle_image_display_set_scale(priv->imageDisplay, 0.0);
2363 entangle_image_display_set_autoscale(priv->imageDisplay, FALSE);
2364 do_zoom_widget_sensitivity(manager);
2368 static void entangle_camera_manager_zoom_best(EntangleCameraManager *manager)
2370 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2372 EntangleCameraManagerPrivate *priv = manager->priv;
2374 priv->zoomLevel = 0;
2375 entangle_image_display_set_autoscale(priv->imageDisplay, TRUE);
2376 do_zoom_widget_sensitivity(manager);
2380 void do_toolbar_zoom_in(GtkToolButton *src G_GNUC_UNUSED,
2381 EntangleCameraManager *manager)
2383 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2385 entangle_camera_manager_zoom_in(manager);
2389 void do_toolbar_zoom_out(GtkToolButton *src G_GNUC_UNUSED,
2390 EntangleCameraManager *manager)
2392 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2394 entangle_camera_manager_zoom_out(manager);
2398 void do_toolbar_zoom_normal(GtkToolButton *src G_GNUC_UNUSED,
2399 EntangleCameraManager *manager)
2401 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2403 entangle_camera_manager_zoom_normal(manager);
2407 void do_toolbar_zoom_best(GtkToolButton *src G_GNUC_UNUSED,
2408 EntangleCameraManager *manager)
2410 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2412 entangle_camera_manager_zoom_best(manager);
2416 void do_menu_zoom_in(GtkImageMenuItem *src G_GNUC_UNUSED,
2417 EntangleCameraManager *manager)
2419 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2421 entangle_camera_manager_zoom_in(manager);
2425 void do_menu_zoom_out(GtkImageMenuItem *src G_GNUC_UNUSED,
2426 EntangleCameraManager *manager)
2428 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2430 entangle_camera_manager_zoom_out(manager);
2433 void do_menu_zoom_normal(GtkImageMenuItem *src G_GNUC_UNUSED,
2434 EntangleCameraManager *manager)
2436 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2438 entangle_camera_manager_zoom_normal(manager);
2441 void do_menu_zoom_best(GtkImageMenuItem *src G_GNUC_UNUSED,
2442 EntangleCameraManager *manager)
2444 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2446 entangle_camera_manager_zoom_best(manager);
2450 void do_toolbar_fullscreen(GtkToggleToolButton *src,
2451 EntangleCameraManager *manager)
2453 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2455 EntangleCameraManagerPrivate *priv = manager->priv;
2456 GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-fullscreen"));
2457 GtkWidget *menubar = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menubar"));
2459 if (gtk_toggle_tool_button_get_active(src)) {
2460 if (0) gtk_widget_hide(menubar);
2461 gtk_window_fullscreen(GTK_WINDOW(manager));
2463 gtk_window_unfullscreen(GTK_WINDOW(manager));
2464 if (0) gtk_widget_show(menubar);
2467 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu)) !=
2468 gtk_toggle_tool_button_get_active(src))
2469 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu),
2470 gtk_toggle_tool_button_get_active(src));
2474 void do_menu_fullscreen(GtkCheckMenuItem *src,
2475 EntangleCameraManager *manager)
2477 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2479 EntangleCameraManagerPrivate *priv = manager->priv;
2480 GtkWidget *tool = GTK_WIDGET(gtk_builder_get_object(priv->builder, "toolbar-fullscreen"));
2481 GtkWidget *menubar = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menubar"));
2483 if (gtk_check_menu_item_get_active(src)) {
2484 gtk_widget_hide(menubar);
2485 gtk_window_fullscreen(GTK_WINDOW(manager));
2487 gtk_window_unfullscreen(GTK_WINDOW(manager));
2488 gtk_widget_show(menubar);
2491 if (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(tool)) !=
2492 gtk_check_menu_item_get_active(src))
2493 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(tool),
2494 gtk_check_menu_item_get_active(src));
2498 static void do_presentation_end(EntangleImagePopup *popup G_GNUC_UNUSED,
2499 EntangleCameraManager *manager)
2501 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2503 EntangleCameraManagerPrivate *priv = manager->priv;
2504 GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-presentation"));
2506 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu), FALSE);
2509 void do_menu_presentation(GtkCheckMenuItem *src,
2510 EntangleCameraManager *manager)
2512 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2514 EntangleCameraManagerPrivate *priv = manager->priv;
2516 if (gtk_check_menu_item_get_active(src)) {
2517 if (!priv->imagePresentation) {
2518 priv->imagePresentation = entangle_image_popup_new();
2519 g_signal_connect(priv->imagePresentation, "popup-close", G_CALLBACK(do_presentation_end), manager);
2521 entangle_image_popup_set_image(priv->imagePresentation, priv->currentImage);
2522 entangle_image_popup_show_on_monitor(priv->imagePresentation,
2523 priv->presentationMonitor);
2524 } else if (priv->imagePresentation) {
2525 gtk_widget_hide(GTK_WIDGET(priv->imagePresentation));
2526 g_object_unref(priv->imagePresentation);
2527 priv->imagePresentation = NULL;
2532 void do_menu_preferences(GtkCheckMenuItem *src G_GNUC_UNUSED,
2533 EntangleCameraManager *manager)
2535 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2537 EntangleCameraManagerPrivate *priv = manager->priv;
2538 if (priv->prefsDisplay == NULL) {
2539 GtkApplication *app = gtk_window_get_application(GTK_WINDOW(manager));
2540 priv->prefsDisplay = entangle_preferences_display_new();
2541 gtk_application_add_window(app, GTK_WINDOW(priv->prefsDisplay));
2542 gtk_window_set_transient_for(GTK_WINDOW(priv->prefsDisplay),
2543 GTK_WINDOW(manager));
2546 gtk_widget_show(GTK_WIDGET(priv->prefsDisplay));
2550 void do_menu_close(GtkMenuItem *src G_GNUC_UNUSED,
2551 EntangleCameraManager *manager)
2553 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2555 gtk_widget_destroy(GTK_WIDGET(manager));
2559 void do_menu_quit(GtkMenuItem *src G_GNUC_UNUSED,
2560 EntangleCameraManager *manager)
2562 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2564 GtkApplication *app = gtk_window_get_application(GTK_WINDOW(manager));
2565 GList *windows = gtk_application_get_windows(app);
2566 GList *tmp = g_list_copy(windows);
2569 GtkWidget *window = GTK_WIDGET(tmp->data);
2570 gtk_widget_destroy(window);
2577 void do_menu_help_about(GtkMenuItem *src G_GNUC_UNUSED,
2578 EntangleCameraManager *manager)
2580 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2582 EntangleCameraManagerPrivate *priv = manager->priv;
2585 priv->about = entangle_help_about_new();
2586 gtk_window_set_transient_for(GTK_WINDOW(priv->about),
2587 GTK_WINDOW(manager));
2590 gtk_widget_show(GTK_WIDGET(priv->about));
2594 static void do_picker_refresh(EntangleCameraPicker *picker G_GNUC_UNUSED, EntangleCameraManager *manager)
2596 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2598 EntangleApplication *app = ENTANGLE_APPLICATION(gtk_window_get_application(GTK_WINDOW(manager)));
2599 EntangleCameraList *list = entangle_application_get_cameras(app);
2600 entangle_camera_list_refresh(list, NULL);
2604 static void do_picker_connect(EntangleCameraPicker *picker G_GNUC_UNUSED,
2605 EntangleCamera *cam,
2608 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
2609 g_return_if_fail(ENTANGLE_IS_CAMERA(cam));
2611 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(data);
2612 EntangleCameraManagerPrivate *priv = manager->priv;
2614 GError *error = NULL;
2615 ENTANGLE_DEBUG("emit connect %p %s", cam, entangle_camera_get_model(cam));
2616 if (need_camera_unmount(cam))
2617 do_camera_unmount(cam);
2619 while (!entangle_camera_connect(cam, &error)) {
2621 GtkWidget *msg = gtk_message_dialog_new(NULL,
2625 _("Unable to connect to camera: %s"),
2627 g_error_free(error);
2629 gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(msg),
2631 _("Check that the camera is not\n\n"
2632 " - opened by another photo <b>application</b>\n"
2633 " - mounted as a <b>filesystem</b> on the desktop\n"
2634 " - in <b>sleep mode</b> to save battery power\n"));
2636 gtk_dialog_add_button(GTK_DIALOG(msg), _("Cancel"), GTK_RESPONSE_CANCEL);
2637 gtk_dialog_add_button(GTK_DIALOG(msg), _("Retry"), GTK_RESPONSE_ACCEPT);
2638 gtk_dialog_set_default_response(GTK_DIALOG(msg), GTK_RESPONSE_ACCEPT);
2640 response = gtk_dialog_run(GTK_DIALOG(msg));
2642 gtk_widget_destroy(msg);
2644 if (response == GTK_RESPONSE_CANCEL)
2648 entangle_camera_manager_set_camera(manager, cam);
2649 gtk_widget_hide(GTK_WIDGET(priv->picker));
2653 static void do_camera_connect(EntangleCameraManager *manager)
2655 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2657 EntangleCameraManagerPrivate *priv = manager->priv;
2658 EntangleApplication *app = ENTANGLE_APPLICATION(gtk_window_get_application(GTK_WINDOW(manager)));
2659 EntangleCameraList *cameras = entangle_application_get_cameras(app);
2661 if (!priv->picker) {
2662 priv->picker = entangle_camera_picker_new();
2663 entangle_camera_picker_set_camera_list(priv->picker, cameras);
2664 gtk_window_set_transient_for(GTK_WINDOW(priv->picker),
2665 GTK_WINDOW(manager));
2666 g_signal_connect(priv->picker, "picker-refresh", G_CALLBACK(do_picker_refresh), manager);
2667 g_signal_connect(priv->picker, "picker-connect", G_CALLBACK(do_picker_connect), manager);
2670 gtk_widget_show(GTK_WIDGET(priv->picker));
2674 void do_menu_connect(GtkMenuItem *src G_GNUC_UNUSED,
2675 EntangleCameraManager *manager)
2677 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2679 do_camera_connect(manager);
2683 void do_menu_disconnect(GtkMenuItem *src G_GNUC_UNUSED,
2684 EntangleCameraManager *manager)
2686 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2688 entangle_camera_manager_set_camera(manager, NULL);
2692 static void do_session_image_selected(GtkIconView *view G_GNUC_UNUSED,
2695 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
2697 EntangleCameraManager *manager = data;
2698 EntangleCameraManagerPrivate *priv = manager->priv;
2699 EntangleImage *img = entangle_session_browser_selected_image(priv->sessionBrowser);
2701 ENTANGLE_DEBUG("Image selection changed");
2703 ENTANGLE_DEBUG("Try load");
2704 do_select_image(manager, img);
2705 g_object_unref(img);
2710 void do_menu_session_open_activate(GtkMenuItem *item G_GNUC_UNUSED,
2711 EntangleCameraManager *manager)
2713 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2715 EntangleCameraManagerPrivate *priv = manager->priv;
2716 gchar *ctype = NULL;
2717 GList *files = NULL;
2718 GAppInfo *info = NULL;
2719 const gchar *filename;
2721 if (!priv->sessionBrowserImage)
2724 filename = entangle_image_get_filename(priv->sessionBrowserImage);
2725 ctype = g_content_type_guess(filename,
2730 info = g_app_info_get_default_for_type(ctype, FALSE);
2735 files = g_list_append(files, g_file_new_for_path(filename));
2737 g_app_info_launch(info, files, NULL, NULL);
2739 g_list_foreach(files, (GFunc)g_object_unref, NULL);
2744 void do_menu_session_delete_activate(GtkMenuItem *item G_GNUC_UNUSED,
2745 EntangleCameraManager *manager)
2747 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2749 EntangleCameraManagerPrivate *priv = manager->priv;
2750 GError *error = NULL;
2752 if (!priv->sessionBrowserImage)
2755 if (!entangle_image_delete(priv->sessionBrowserImage, &error)) {
2756 do_camera_task_error(manager, _("Delete"), error);
2759 entangle_session_remove(priv->session, priv->sessionBrowserImage);
2763 static void do_session_browser_open_with_app(GtkMenuItem *src,
2764 EntangleCameraManager *manager)
2766 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2768 EntangleCameraManagerPrivate *priv = manager->priv;
2769 GAppInfo *info = g_object_get_data(G_OBJECT(src), "appinfo");
2770 GList *files = NULL;
2771 const gchar *filename;
2776 if (!priv->sessionBrowserImage)
2779 filename = entangle_image_get_filename(priv->sessionBrowserImage);
2780 files = g_list_append(files, g_file_new_for_path(filename));
2782 g_app_info_launch(info, files, NULL, NULL);
2784 g_list_foreach(files, (GFunc)g_object_unref, NULL);
2789 static void do_session_browser_open_with_select(GtkMenuItem *src G_GNUC_UNUSED,
2790 EntangleCameraManager *manager)
2792 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2794 EntangleCameraManagerPrivate *priv = manager->priv;
2798 GList *files = NULL;
2800 if (!priv->sessionBrowserImage)
2803 file = g_file_new_for_path(entangle_image_get_filename(priv->sessionBrowserImage));
2804 dialog = GTK_DIALOG(gtk_app_chooser_dialog_new(GTK_WINDOW(manager),
2805 GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,
2808 gtk_dialog_run(dialog);
2810 info = gtk_app_chooser_get_app_info(GTK_APP_CHOOSER(dialog));
2812 files = g_list_append(files, file);
2815 g_app_info_launch(info, files, NULL, NULL);
2817 g_list_foreach(files, (GFunc)g_object_unref, NULL);
2819 gtk_widget_destroy(GTK_WIDGET(dialog));
2823 static gboolean do_session_browser_popup(EntangleSessionBrowser *browser,
2824 GdkEventButton *event,
2825 EntangleCameraManager *manager)
2827 g_return_val_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager), FALSE);
2829 EntangleCameraManagerPrivate *priv = manager->priv;
2831 GtkWidget *openWith;
2834 gchar *ctype = NULL;
2835 GList *appInfoList = NULL;
2836 const gchar *filename;
2838 if (event->type != GDK_BUTTON_PRESS)
2840 if (event->button != 3)
2843 priv->sessionBrowserImage = entangle_session_browser_get_image_at_coords(browser,
2847 if (!priv->sessionBrowserImage)
2850 filename = entangle_image_get_filename(priv->sessionBrowserImage);
2852 open = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-session-open"));
2853 openWith = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-session-open-with"));
2855 ctype = g_content_type_guess(filename,
2860 appInfoList = g_app_info_get_all_for_type(ctype);
2862 appList = GTK_MENU(gtk_menu_new());
2865 GList *tmp = appInfoList;
2867 GAppInfo *appInfo = tmp->data;
2869 child = GTK_MENU_ITEM(gtk_menu_item_new_with_label
2870 (g_app_info_get_display_name(appInfo)));
2871 g_signal_connect(child, "activate",
2872 G_CALLBACK(do_session_browser_open_with_app), manager);
2873 g_object_set_data_full(G_OBJECT(child), "appinfo",
2874 appInfo, (GDestroyNotify)g_object_unref);
2875 gtk_container_add(GTK_CONTAINER(appList), GTK_WIDGET(child));
2879 g_list_free(appInfoList);
2881 child = GTK_MENU_ITEM(gtk_separator_menu_item_new());
2882 gtk_container_add(GTK_CONTAINER(appList), GTK_WIDGET(child));
2885 child = GTK_MENU_ITEM(gtk_menu_item_new_with_label(_("Select application...")));
2886 g_signal_connect(child, "activate",
2887 G_CALLBACK(do_session_browser_open_with_select), manager);
2888 gtk_container_add(GTK_CONTAINER(appList), GTK_WIDGET(child));
2890 gtk_widget_show_all(GTK_WIDGET(appList));
2892 gtk_menu_item_set_submenu(GTK_MENU_ITEM(openWith), GTK_WIDGET(appList));
2894 gtk_menu_popup(priv->sessionBrowserMenu,
2895 NULL, NULL, NULL, NULL,
2896 event->button, event->time);
2899 gtk_widget_set_sensitive(GTK_WIDGET(open), ctype && appInfoList ? TRUE : FALSE);
2904 static void do_popup_close(EntangleImagePopup *popup,
2905 EntangleCameraManager *manager)
2907 g_return_if_fail(ENTANGLE_IS_IMAGE_POPUP(popup));
2908 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
2910 EntangleCameraManagerPrivate *priv = manager->priv;
2911 EntangleImage *img = entangle_image_popup_get_image(popup);
2912 const char *filename = entangle_image_get_filename(img);
2914 g_hash_table_remove(priv->popups, filename);
2916 entangle_pixbuf_loader_unload(ENTANGLE_PIXBUF_LOADER(priv->imageLoader),
2921 static void do_session_browser_drag_failed(GtkWidget *widget G_GNUC_UNUSED,
2922 GdkDragContext *ctx G_GNUC_UNUSED,
2926 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
2928 EntangleCameraManager *manager = data;
2929 EntangleCameraManagerPrivate *priv = manager->priv;
2931 if (res == GTK_DRAG_RESULT_NO_TARGET) {
2932 EntangleImage *img = entangle_session_browser_selected_image(priv->sessionBrowser);
2936 GdkDeviceManager *devmgr;
2939 devmgr = gdk_display_get_device_manager(gtk_widget_get_display(widget));
2940 dev = gdk_device_manager_get_client_pointer(devmgr);
2941 gdk_device_get_position(dev,
2945 const gchar *filename = entangle_image_get_filename(img);
2946 EntangleImagePopup *pol;
2947 if (!(pol = g_hash_table_lookup(priv->popups, filename))) {
2948 pol = entangle_image_popup_new();
2949 entangle_image_popup_set_image(pol, img);
2950 g_signal_connect(pol, "hide", G_CALLBACK(do_popup_close), manager);
2951 g_hash_table_insert(priv->popups, g_strdup(filename), pol);
2952 entangle_pixbuf_loader_load(ENTANGLE_PIXBUF_LOADER(priv->imageLoader),
2955 ENTANGLE_DEBUG("Popup %p for %s", pol, filename);
2956 entangle_image_popup_show(pol, GTK_WINDOW(manager), x, y);
2957 g_object_unref(img);
2963 static void do_pixbuf_loaded(EntanglePixbufLoader *loader,
2964 EntangleImage *image)
2966 g_return_if_fail(ENTANGLE_IS_IMAGE(image));
2968 GdkPixbuf *pixbuf = entangle_pixbuf_loader_get_pixbuf(loader, image);
2970 entangle_image_set_pixbuf(image, pixbuf);
2974 static void do_metadata_loaded(EntanglePixbufLoader *loader,
2975 EntangleImage *image)
2977 g_return_if_fail(ENTANGLE_IS_IMAGE(image));
2979 GExiv2Metadata *metadata = entangle_pixbuf_loader_get_metadata(loader, image);
2981 entangle_image_set_metadata(image, metadata);
2985 static void do_pixbuf_unloaded(EntanglePixbufLoader *loader G_GNUC_UNUSED,
2986 EntangleImage *image)
2988 g_return_if_fail(ENTANGLE_IS_IMAGE(image));
2990 entangle_image_set_pixbuf(image, NULL);
2994 static void do_metadata_unloaded(EntanglePixbufLoader *loader G_GNUC_UNUSED,
2995 EntangleImage *image)
2997 g_return_if_fail(ENTANGLE_IS_IMAGE(image));
2999 entangle_image_set_metadata(image, NULL);
3003 static gboolean do_image_status_hide(gpointer data)
3005 g_return_val_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data), FALSE);
3007 EntangleCameraManager *manager = data;
3008 EntangleCameraManagerPrivate *priv = manager->priv;
3010 entangle_auto_drawer_set_pinned(ENTANGLE_AUTO_DRAWER(priv->imageDrawer), FALSE);
3011 priv->imageDrawerTimer = 0;
3016 static void do_image_status_show(GtkWidget *widget G_GNUC_UNUSED,
3017 GdkEvent *event G_GNUC_UNUSED,
3020 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(data));
3022 EntangleCameraManager *manager = data;
3023 EntangleCameraManagerPrivate *priv = manager->priv;
3025 entangle_auto_drawer_set_pinned(ENTANGLE_AUTO_DRAWER(priv->imageDrawer), TRUE);
3026 if (priv->imageDrawerTimer)
3027 g_source_remove(priv->imageDrawerTimer);
3028 priv->imageDrawerTimer = g_timeout_add_seconds(3,
3029 do_image_status_hide,
3034 static void do_entangle_camera_manager_hide(EntangleCameraManager *manager)
3036 g_return_if_fail(ENTANGLE_IS_CAMERA_MANAGER(manager));
3038 EntangleCameraManagerPrivate *priv = manager->priv;
3040 entangle_camera_manager_set_camera(manager, NULL);
3042 ENTANGLE_DEBUG("Removing all popups");
3043 g_hash_table_remove_all(priv->popups);
3047 static void do_entangle_camera_manager_set_builder(EntangleWindow *window,
3048 GtkBuilder *builder)
3050 EntangleCameraManager *manager = ENTANGLE_CAMERA_MANAGER(window);
3051 EntangleCameraManagerPrivate *priv = manager->priv;
3053 GtkWidget *iconScroll;
3054 GtkWidget *settingsBox;
3055 GtkWidget *settingsViewport;
3057 GtkWidget *monitorMenu;
3058 GtkWidget *imageViewport;
3060 priv->builder = g_object_ref(builder);
3062 menu = GTK_WIDGET(gtk_builder_get_object(priv->builder, "menu-monitor"));
3063 monitorMenu = entangle_camera_manager_monitor_menu(manager);
3064 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu), monitorMenu);
3066 imageViewport = gtk_viewport_new(NULL, NULL);
3067 priv->imageScroll = GTK_SCROLLED_WINDOW
3068 (gtk_scrolled_window_new(gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(imageViewport)),
3069 gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(imageViewport))));
3071 gtk_container_add(GTK_CONTAINER(priv->imageScroll), imageViewport);
3073 priv->imageLoader = entangle_image_loader_new();
3074 priv->thumbLoader = entangle_thumbnail_loader_new(140, 140);
3076 g_signal_connect(priv->imageLoader, "pixbuf-loaded", G_CALLBACK(do_pixbuf_loaded), NULL);
3077 g_signal_connect(priv->imageLoader, "metadata-loaded", G_CALLBACK(do_metadata_loaded), NULL);
3078 g_signal_connect(priv->imageLoader, "pixbuf-unloaded", G_CALLBACK(do_pixbuf_unloaded), NULL);
3079 g_signal_connect(priv->imageLoader, "metadata-unloaded", G_CALLBACK(do_metadata_unloaded), NULL);
3081 priv->imageDisplay = entangle_image_display_new();
3082 priv->imageStatusbar = entangle_image_statusbar_new();
3083 priv->imageDrawer = entangle_auto_drawer_new();
3084 priv->sessionBrowser = entangle_session_browser_new();
3085 priv->sessionBrowserMenu = GTK_MENU(gtk_builder_get_object(priv->builder, "menu-session-browser"));
3086 priv->controlPanel = entangle_control_panel_new();
3087 priv->imageHistogram = entangle_image_histogram_new();
3088 gtk_widget_show(GTK_WIDGET(priv->imageHistogram));
3090 g_object_set(priv->sessionBrowser, "thumbnail-loader", priv->thumbLoader, NULL);
3092 g_signal_connect(priv->imageDisplay, "size-allocate",
3093 G_CALLBACK(do_restore_scroll), manager);
3095 g_signal_connect(priv->sessionBrowser, "selection-changed",
3096 G_CALLBACK(do_session_image_selected), manager);
3097 g_signal_connect(priv->sessionBrowser, "button-press-event",
3098 G_CALLBACK(do_session_browser_popup), manager);
3099 g_signal_connect(priv->sessionBrowser, "drag-failed",
3100 G_CALLBACK(do_session_browser_drag_failed), manager);
3102 settingsBox = GTK_WIDGET(gtk_builder_get_object(priv->builder, "settings-box"));
3103 settingsViewport = GTK_WIDGET(gtk_builder_get_object(priv->builder, "settings-viewport"));
3104 display = GTK_WIDGET(gtk_builder_get_object(priv->builder, "display-panel"));
3106 iconScroll = gtk_scrolled_window_new(NULL, NULL);
3107 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(iconScroll),
3108 GTK_POLICY_AUTOMATIC,
3111 /* XXX match icon size + padding + scrollbar needs */
3112 gtk_widget_set_size_request(settingsBox, 300, 100);
3113 gtk_widget_set_size_request(iconScroll, 140, 170);