~ubuntu-branches/ubuntu/quantal/cheese/quantal

« back to all changes in this revision

Viewing changes to .pc/debian-changes-3.2.2-0ubuntu1/src/cheese-window.vala

  • Committer: Package Import Robot
  • Author(s): Michael Terry
  • Date: 2011-11-22 15:02:36 UTC
  • Revision ID: package-import@ubuntu.com-20111122150236-6fs4o0adktyojxm2
Tags: 3.2.2-0ubuntu2
* debian/control:
  - Drop Vcs-Bzr and update maintainer; this is in universe, not maintained
    by the Desktop Team.
* debian/patches/debian-changes-3.2.2-0ubuntu1:
  - Dropped, looks like an accidental change
* debian/patches/add-missing-cheese-common-vapi.patch:
  - Add missing file from the tarball, grabbed from bzr.  Fixes FTBFS

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2010 Yuvaraj Pandian T <yuvipanda@yuvi.in>
3
 
 * Copyright © 2010 daniel g. siegel <dgsiegel@gnome.org>
4
 
 * Copyright © 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
5
 
 *
6
 
 * Licensed under the GNU General Public License Version 2
7
 
 *
8
 
 * This program is free software; you can redistribute it and/or modify
9
 
 * it under the terms of the GNU General Public License as published by
10
 
 * the Free Software Foundation; either version 2 of the License, or
11
 
 * (at your option) any later version.
12
 
 *
13
 
 * This program is distributed in the hope that it will be useful,
14
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
 * GNU General Public License for more details.
17
 
 *
18
 
 * You should have received a copy of the GNU General Public License
19
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 
 */
21
 
 
22
 
using Gtk;
23
 
using Gdk;
24
 
using GtkClutter;
25
 
using Clutter;
26
 
using Config;
27
 
using Eog;
28
 
using Gst;
29
 
using Gee;
30
 
using CanberraGtk;
31
 
 
32
 
const int FULLSCREEN_TIMEOUT_INTERVAL = 5 * 1000;
33
 
const int EFFECTS_PER_PAGE            = 9;
34
 
 
35
 
public class Cheese.MainWindow : Gtk.Window
36
 
{
37
 
  private MediaMode current_mode;
38
 
 
39
 
  private Gtk.Builder    gtk_builder;
40
 
  private Clutter.Script clutter_builder;
41
 
 
42
 
  private GLib.Settings settings;
43
 
 
44
 
  private Gtk.Widget       thumbnails;
45
 
  private GtkClutter.Embed viewport_widget;
46
 
  private Gtk.VBox         main_vbox;
47
 
  private Eog.ThumbNav     thumb_nav;
48
 
  private Cheese.ThumbView thumb_view;
49
 
  private Gtk.Alignment    thumbnails_right;
50
 
  private Gtk.Alignment    thumbnails_bottom;
51
 
  private Gtk.MenuBar      menubar;
52
 
  private Gtk.HBox         leave_fullscreen_button_container;
53
 
  private Gtk.ToggleButton photo_toggle_button;
54
 
  private Gtk.ToggleButton video_toggle_button;
55
 
  private Gtk.ToggleButton burst_toggle_button;
56
 
  private Gtk.Button       take_action_button;
57
 
  private Gtk.Label        take_action_button_label;
58
 
  private Gtk.Image        take_action_button_image;
59
 
  private Gtk.ToggleButton effects_toggle_button;
60
 
  private Gtk.Button       leave_fullscreen_button;
61
 
  private Gtk.HBox         buttons_area;
62
 
  private Gtk.Menu         thumbnail_popup;
63
 
 
64
 
  private Clutter.Stage     viewport;
65
 
  private Clutter.Box       viewport_layout;
66
 
  private Clutter.Texture   video_preview;
67
 
  private Clutter.BinLayout viewport_layout_manager;
68
 
  private Clutter.Text      countdown_layer;
69
 
  private Clutter.Rectangle background_layer;
70
 
  private Clutter.Text      error_layer;
71
 
 
72
 
  private Clutter.Box           current_effects_grid;
73
 
  private int                current_effects_page = 0;
74
 
  private ArrayList<Clutter.Box> effects_grids;
75
 
 
76
 
  private Gtk.Action       take_photo_action;
77
 
  private Gtk.Action       take_video_action;
78
 
  private Gtk.Action       take_burst_action;
79
 
  private Gtk.Action       photo_mode_action;
80
 
  private Gtk.Action       video_mode_action;
81
 
  private Gtk.Action       burst_mode_action;
82
 
  private Gtk.ToggleAction effects_toggle_action;
83
 
  private Gtk.ToggleAction wide_mode_action;
84
 
  private Gtk.ToggleAction fullscreen_action;
85
 
  private Gtk.Action       countdown_action;
86
 
  private Gtk.Action       effects_page_prev_action;
87
 
  private Gtk.Action       effects_page_next_action;
88
 
 
89
 
  private bool is_fullscreen;
90
 
  private bool is_wide_mode;
91
 
  private bool is_recording;       /* Video Recording Flag */
92
 
  private bool is_bursting;
93
 
  private bool is_effects_selector_active;
94
 
  private bool is_camera_actions_sensitive;
95
 
  private bool action_cancelled;
96
 
  private bool is_command_line_startup;
97
 
 
98
 
  private Gtk.Button[] buttons;
99
 
 
100
 
  private Cheese.Camera   camera;
101
 
  private Cheese.FileUtil fileutil;
102
 
  private Cheese.Flash    flash;
103
 
 
104
 
  private Cheese.EffectsManager    effects_manager;
105
 
  private Cheese.PreferencesDialog preferences_dialog;
106
 
 
107
 
  private Cheese.Effect selected_effect;
108
 
 
109
 
  [CCode (instance_pos = -1)]
110
 
  public void on_quit (Gtk.Action action)
111
 
  {
112
 
    destroy ();
113
 
  }
114
 
 
115
 
  [CCode (instance_pos = -1)]
116
 
  public void on_preferences_dialog (Gtk.Action action)
117
 
  {
118
 
    if (preferences_dialog == null)
119
 
      preferences_dialog = new Cheese.PreferencesDialog (camera, settings);
120
 
    preferences_dialog.set_current_mode (current_mode);
121
 
    preferences_dialog.show ();
122
 
  }
123
 
 
124
 
  public bool on_thumbnail_mouse_button_press (Gtk.Widget      iconview,
125
 
                                               Gdk.EventButton event)
126
 
  {
127
 
    Gtk.TreePath path;
128
 
    path = thumb_view.get_path_at_pos ((int) event.x, (int) event.y);
129
 
 
130
 
    if (path == null)
131
 
      return false;
132
 
 
133
 
    if (!thumb_view.path_is_selected (path))
134
 
    {
135
 
      thumb_view.unselect_all ();
136
 
      thumb_view.select_path (path);
137
 
      thumb_view.set_cursor (path, null, false);
138
 
    }
139
 
 
140
 
    if (event.type == Gdk.EventType.BUTTON_PRESS)
141
 
    {
142
 
      if (event.button == 3)
143
 
      {
144
 
        thumbnail_popup.popup (null, thumb_view, null, event.button, event.time);
145
 
      }
146
 
    }
147
 
    else
148
 
    if (event.type == Gdk.EventType.2BUTTON_PRESS)
149
 
    {
150
 
      on_file_open (null);
151
 
    }
152
 
 
153
 
    return false;
154
 
  }
155
 
 
156
 
  [CCode (instance_pos = -1)]
157
 
  public void on_file_open (Gtk.Action ? action)
158
 
  {
159
 
    string filename, uri;
160
 
 
161
 
    Gdk.Screen screen;
162
 
    filename = thumb_view.get_selected_image ();
163
 
 
164
 
    if (filename == null)
165
 
      return;                     /* Nothing selected. */
166
 
 
167
 
    try
168
 
    {
169
 
      uri    = GLib.Filename.to_uri (filename);
170
 
      screen = this.get_screen ();
171
 
      Gtk.show_uri (screen, uri, Gtk.get_current_event_time ());
172
 
    }
173
 
    catch (Error err)
174
 
    {
175
 
      MessageDialog error_dialog = new MessageDialog (this,
176
 
                                                      Gtk.DialogFlags.MODAL |
177
 
                                                      Gtk.DialogFlags.DESTROY_WITH_PARENT,
178
 
                                                      Gtk.MessageType.ERROR,
179
 
                                                      Gtk.ButtonsType.OK,
180
 
                                                      "Could not open %s",
181
 
                                                      filename);
182
 
 
183
 
      error_dialog.run ();
184
 
      error_dialog.destroy ();
185
 
    }
186
 
  }
187
 
 
188
 
  [CCode (instance_pos = -1)]
189
 
  public void on_file_delete (Gtk.Action action)
190
 
  {
191
 
    File file;
192
 
    int response;
193
 
    MessageDialog confirmation_dialog;
194
 
 
195
 
    GLib.List<GLib.File> files = thumb_view.get_selected_images_list ();
196
 
 
197
 
    for (int i = 0; i < files.length (); i++)
198
 
    {
199
 
      file = files<GLib.File>.nth (i).data;
200
 
      if (file == null)
201
 
        return;
202
 
 
203
 
      confirmation_dialog = new MessageDialog.with_markup (this,
204
 
                                                           Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
205
 
                                                           Gtk.MessageType.WARNING,
206
 
                                                           Gtk.ButtonsType.NONE,
207
 
                                                           "Are you sure you want to permanently delete the file \"%s\"?",
208
 
                                                           file.get_basename ());
209
 
      confirmation_dialog.add_button (Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL);
210
 
      confirmation_dialog.add_button (Gtk.Stock.DELETE, Gtk.ResponseType.ACCEPT);
211
 
      confirmation_dialog.format_secondary_text ("%s", "If you delete an item, it will be permanently lost");
212
 
      response = confirmation_dialog.run ();
213
 
      confirmation_dialog.destroy ();
214
 
      if (response == Gtk.ResponseType.ACCEPT)
215
 
      {
216
 
        try
217
 
        {
218
 
          file.delete (null);
219
 
        }
220
 
        catch (Error err)
221
 
        {
222
 
          MessageDialog error_dialog = new MessageDialog (this,
223
 
                                                          Gtk.DialogFlags.MODAL |
224
 
                                                          Gtk.DialogFlags.DESTROY_WITH_PARENT,
225
 
                                                          Gtk.MessageType.ERROR,
226
 
                                                          Gtk.ButtonsType.OK,
227
 
                                                          "Could not delete %s",
228
 
                                                          file.get_path ());
229
 
 
230
 
          error_dialog.run ();
231
 
          error_dialog.destroy ();
232
 
        }
233
 
      }
234
 
    }
235
 
  }
236
 
 
237
 
  [CCode (instance_pos = -1)]
238
 
  public void on_file_move_to_trash (Gtk.Action action)
239
 
  {
240
 
    File file;
241
 
 
242
 
    GLib.List<GLib.File> files = thumb_view.get_selected_images_list ();
243
 
 
244
 
    for (int i = 0; i < files.length (); i++)
245
 
    {
246
 
      file = files<GLib.File>.nth (i).data;
247
 
      if (file == null)
248
 
        return;
249
 
 
250
 
      try
251
 
      {
252
 
        file.trash (null);
253
 
      }
254
 
      catch (Error err)
255
 
      {
256
 
        MessageDialog error_dialog = new MessageDialog (this,
257
 
                                                        Gtk.DialogFlags.MODAL |
258
 
                                                        Gtk.DialogFlags.DESTROY_WITH_PARENT,
259
 
                                                        Gtk.MessageType.ERROR,
260
 
                                                        Gtk.ButtonsType.OK,
261
 
                                                        "Could not move %s to trash",
262
 
                                                        file.get_path ());
263
 
 
264
 
        error_dialog.run ();
265
 
        error_dialog.destroy ();
266
 
      }
267
 
    }
268
 
  }
269
 
 
270
 
  [CCode (instance_pos = -1)]
271
 
  public void on_file_move_to_trash_all (Gtk.Action action)
272
 
  {
273
 
    try {
274
 
      File           file_to_trash;
275
 
      FileInfo       file_info;
276
 
      File           directory  = File.new_for_path (fileutil.get_photo_path ());
277
 
      FileEnumerator enumerator = directory.enumerate_children (FILE_ATTRIBUTE_STANDARD_NAME, 0, null);
278
 
 
279
 
      while ((file_info = enumerator.next_file (null)) != null)
280
 
      {
281
 
        file_to_trash = File.new_for_path (fileutil.get_photo_path () + GLib.Path.DIR_SEPARATOR_S + file_info.get_name ());
282
 
        file_to_trash.trash (null);
283
 
      }
284
 
 
285
 
      directory  = File.new_for_path (fileutil.get_video_path ());
286
 
      enumerator = directory.enumerate_children (FILE_ATTRIBUTE_STANDARD_NAME, 0, null);
287
 
 
288
 
      while ((file_info = enumerator.next_file (null)) != null)
289
 
      {
290
 
        file_to_trash = File.new_for_path (fileutil.get_photo_path () + GLib.Path.DIR_SEPARATOR_S + file_info.get_name ());
291
 
        file_to_trash.trash (null);
292
 
      }
293
 
    } catch (Error e)
294
 
    {
295
 
      warning ("Error: %s\n", e.message);
296
 
      return;
297
 
    }
298
 
  }
299
 
 
300
 
  [CCode (instance_pos = -1)]
301
 
  public void on_file_save_as (Gtk.Action action)
302
 
  {
303
 
    string            filename, basename;
304
 
    FileChooserDialog save_as_dialog;
305
 
    int               response;
306
 
 
307
 
    filename = thumb_view.get_selected_image ();
308
 
    if (filename == null)
309
 
      return;                    /* Nothing selected. */
310
 
 
311
 
    save_as_dialog = new FileChooserDialog ("Save File",
312
 
                                            this,
313
 
                                            Gtk.FileChooserAction.SAVE,
314
 
                                            Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL,
315
 
                                            Gtk.Stock.SAVE, Gtk.ResponseType.ACCEPT,
316
 
                                            null);
317
 
 
318
 
    save_as_dialog.do_overwrite_confirmation = true;
319
 
    basename                                 = GLib.Filename.display_basename (filename);
320
 
    save_as_dialog.set_current_name (basename);
321
 
    save_as_dialog.set_current_folder (GLib.Environment.get_home_dir ());
322
 
 
323
 
    response = save_as_dialog.run ();
324
 
 
325
 
    save_as_dialog.hide ();
326
 
    if (response == Gtk.ResponseType.ACCEPT)
327
 
    {
328
 
      string target_filename;
329
 
      target_filename = save_as_dialog.get_filename ();
330
 
 
331
 
      File src  = File.new_for_path (filename);
332
 
      File dest = File.new_for_path (target_filename);
333
 
 
334
 
      try
335
 
      {
336
 
        src.copy (dest, FileCopyFlags.OVERWRITE, null, null);
337
 
      }
338
 
      catch (Error err)
339
 
      {
340
 
        MessageDialog error_dialog = new MessageDialog (this,
341
 
                                                        Gtk.DialogFlags.MODAL |
342
 
                                                        Gtk.DialogFlags.DESTROY_WITH_PARENT,
343
 
                                                        Gtk.MessageType.ERROR,
344
 
                                                        Gtk.ButtonsType.OK,
345
 
                                                        "Could not save %s",
346
 
                                                        target_filename);
347
 
 
348
 
        error_dialog.run ();
349
 
        error_dialog.destroy ();
350
 
      }
351
 
    }
352
 
    save_as_dialog.destroy ();
353
 
  }
354
 
 
355
 
  [CCode (instance_pos = -1)]
356
 
  public void on_help_contents (Gtk.Action action)
357
 
  {
358
 
    Gdk.Screen screen;
359
 
    screen = this.get_screen ();
360
 
    try {
361
 
      Gtk.show_uri (screen, "ghelp:cheese", Gtk.get_current_event_time ());
362
 
    } catch (Error err)
363
 
    {
364
 
      warning ("Error: %s\n", err.message);
365
 
    }
366
 
  }
367
 
 
368
 
  [CCode (instance_pos = -1)]
369
 
  public void on_help_about (Gtk.Action action)
370
 
  {
371
 
    Gtk.AboutDialog about_dialog;
372
 
    about_dialog         = (Gtk.AboutDialog)gtk_builder.get_object ("aboutdialog");
373
 
    about_dialog.set_transient_for (this);
374
 
    about_dialog.set_modal (true);
375
 
    about_dialog.version = Config.VERSION;
376
 
    about_dialog.run ();
377
 
    about_dialog.hide ();
378
 
  }
379
 
 
380
 
  [CCode (instance_pos = -1)]
381
 
  public void on_layout_wide_mode (ToggleAction action)
382
 
  {
383
 
    if (!is_command_line_startup)
384
 
    {
385
 
     /* Don't save to settings when using -w mode from command-line, so
386
 
      * command-line options change the mode for one run only. */
387
 
      settings.set_boolean ("wide-mode", action.active);
388
 
    }
389
 
    set_wide_mode (action.active);
390
 
  }
391
 
 
392
 
  [CCode (instance_pos = -1)]
393
 
  public void on_layout_fullscreen (ToggleAction action)
394
 
  {
395
 
    if (!is_command_line_startup)
396
 
    {
397
 
     /* Don't save to settings when using -f mode from command-line, so
398
 
      * command-line options change the mode for one run only. */
399
 
      settings.set_boolean ("fullscreen", action.active);
400
 
    }
401
 
    set_fullscreen_mode (action.active);
402
 
  }
403
 
 
404
 
  [CCode (instance_pos = -1)]
405
 
  public void on_mode_change (RadioAction action)
406
 
  {
407
 
    set_mode ((MediaMode) action.value);
408
 
  }
409
 
 
410
 
  private void enable_mode_change ()
411
 
  {
412
 
    photo_mode_action.sensitive = true;
413
 
    video_mode_action.sensitive = true;
414
 
    burst_mode_action.sensitive = true;
415
 
    effects_toggle_action.sensitive = true;
416
 
  }
417
 
 
418
 
  private void disable_mode_change ()
419
 
  {
420
 
     photo_mode_action.sensitive = false;
421
 
     video_mode_action.sensitive = false;
422
 
     burst_mode_action.sensitive = false;
423
 
     effects_toggle_action.sensitive = false;
424
 
  }
425
 
 
426
 
  private void set_resolution(MediaMode mode)
427
 
  {
428
 
    if (camera == null)
429
 
      return;
430
 
 
431
 
    unowned GLib.List<VideoFormat> formats = camera.get_video_formats ();
432
 
 
433
 
    if (formats == null)
434
 
      return;
435
 
    
436
 
    unowned Cheese.VideoFormat format;
437
 
    int width = 0;
438
 
    int height = 0;
439
 
 
440
 
    switch (mode)
441
 
    {
442
 
      case MediaMode.PHOTO:
443
 
      case MediaMode.BURST:
444
 
        width  = settings.get_int ("photo-x-resolution");
445
 
        height = settings.get_int ("photo-y-resolution");
446
 
        break;
447
 
      case MediaMode.VIDEO:
448
 
        width  = settings.get_int ("video-x-resolution");
449
 
        height = settings.get_int ("video-y-resolution");
450
 
        break;
451
 
    }
452
 
 
453
 
    for (int i = 0; i < formats.length (); i++)
454
 
    {
455
 
      format = formats<VideoFormat>.nth (i).data;
456
 
      if (width == format.width && height == format.height)
457
 
      {
458
 
        camera.set_video_format (format);
459
 
        break;
460
 
      }
461
 
    }
462
 
  }
463
 
 
464
 
  private void set_mode (MediaMode mode)
465
 
  {
466
 
    this.current_mode = mode;
467
 
    
468
 
    set_resolution (current_mode);
469
 
    
470
 
    if (preferences_dialog != null)
471
 
      preferences_dialog.set_current_mode (current_mode);
472
 
    
473
 
    switch (this.current_mode)
474
 
    {
475
 
      case MediaMode.PHOTO:
476
 
        take_photo_action.sensitive       = true;
477
 
        take_video_action.sensitive       = false;
478
 
        take_burst_action.sensitive       = false;
479
 
        take_action_button.related_action = take_photo_action;
480
 
        break;
481
 
 
482
 
      case MediaMode.VIDEO:
483
 
        take_photo_action.sensitive       = false;
484
 
        take_video_action.sensitive       = true;
485
 
        take_burst_action.sensitive       = false;
486
 
        take_action_button.related_action = take_video_action;
487
 
        break;
488
 
 
489
 
      case MediaMode.BURST:
490
 
        take_photo_action.sensitive       = false;
491
 
        take_video_action.sensitive       = false;
492
 
        take_burst_action.sensitive       = true;
493
 
        take_action_button.related_action = take_burst_action;
494
 
        break;
495
 
    }
496
 
    take_action_button_label.label  = "<b>" + take_action_button.related_action.label + "</b>";
497
 
    take_action_button.tooltip_text = take_action_button.related_action.tooltip;
498
 
}
499
 
 
500
 
  private TimeoutSource fullscreen_timeout;
501
 
  private void clear_fullscreen_timeout ()
502
 
  {
503
 
    if (fullscreen_timeout != null)
504
 
    {
505
 
      fullscreen_timeout.destroy ();
506
 
      fullscreen_timeout = null;
507
 
    }
508
 
  }
509
 
 
510
 
  private void set_fullscreen_timeout ()
511
 
  {
512
 
    fullscreen_timeout = new TimeoutSource (FULLSCREEN_TIMEOUT_INTERVAL);
513
 
    fullscreen_timeout.attach (null);
514
 
    fullscreen_timeout.set_callback (() => {buttons_area.hide ();
515
 
                                            clear_fullscreen_timeout ();
516
 
                                            return true; });
517
 
  }
518
 
 
519
 
  private bool fullscreen_motion_notify_callback (Gtk.Widget viewport, EventMotion e)
520
 
  {
521
 
    /* Start a new timeout at the end of every mouse pointer movement.
522
 
     * So all timeouts will be cancelled, except one at the last pointer movement.
523
 
     * We call show even if the button isn't hidden. */
524
 
    clear_fullscreen_timeout ();
525
 
    buttons_area.show ();
526
 
    set_fullscreen_timeout ();
527
 
    return true;
528
 
  }
529
 
 
530
 
  private void set_fullscreen_mode (bool fullscreen_mode)
531
 
  {
532
 
    /* After the first time the window has been shown using this.show_all (),
533
 
     * the value of leave_fullscreen_button_container.no_show_all should be set to false
534
 
     * So that the next time leave_fullscreen_button_container.show_all () is called, the button is actually shown
535
 
     * FIXME: If this code can be made cleaner/clearer, please do */
536
 
 
537
 
    is_fullscreen = fullscreen_mode;
538
 
    if (fullscreen_mode)
539
 
    {
540
 
      if (is_wide_mode)
541
 
      {
542
 
        thumbnails_right.hide ();
543
 
      }
544
 
      else
545
 
      {
546
 
        thumbnails_bottom.hide ();
547
 
      }
548
 
      menubar.hide ();
549
 
      leave_fullscreen_button_container.no_show_all = false;
550
 
      leave_fullscreen_button_container.show_all ();
551
 
 
552
 
      /* Make all buttons look 'flat' */
553
 
      foreach (Gtk.Button b in buttons)
554
 
      {
555
 
        if (b.get_name () != "take_action_button")
556
 
          b.relief = Gtk.ReliefStyle.NONE;
557
 
      }
558
 
      this.fullscreen ();
559
 
      viewport_widget.motion_notify_event.connect (fullscreen_motion_notify_callback);
560
 
      set_fullscreen_timeout ();
561
 
    }
562
 
    else
563
 
    {
564
 
      if (is_wide_mode)
565
 
      {
566
 
        thumbnails_right.show_all ();
567
 
      }
568
 
      else
569
 
      {
570
 
        thumbnails_bottom.show_all ();
571
 
      }
572
 
      menubar.show_all ();
573
 
      leave_fullscreen_button_container.hide ();
574
 
 
575
 
      /* Make all buttons look, uhm, Normal */
576
 
      foreach (Gtk.Button b in buttons)
577
 
      {
578
 
        if (b.get_name () != "take_action_button")
579
 
          b.relief = Gtk.ReliefStyle.NORMAL;
580
 
      }
581
 
 
582
 
      /* Stop timer so buttons_area does not get hidden after returning from
583
 
       * fullscreen mode */
584
 
      clear_fullscreen_timeout ();
585
 
      /* Show the buttons area anyway - it might've been hidden in fullscreen mode */
586
 
      buttons_area.show ();
587
 
      viewport_widget.motion_notify_event.disconnect (fullscreen_motion_notify_callback);
588
 
      this.unfullscreen ();
589
 
    }
590
 
  }
591
 
 
592
 
  private void set_wide_mode (bool wide_mode)
593
 
  {
594
 
    is_wide_mode = wide_mode;
595
 
 
596
 
    /* keep the viewport to its current size while rearranging the ui,
597
 
     * so that thumbview moves from right to bottom and viceversa
598
 
     * while the rest of the window stays unchanged */
599
 
    Gtk.Allocation alloc;
600
 
    viewport_widget.get_allocation (out alloc);
601
 
    viewport_widget.set_size_request (alloc.width, alloc.height);
602
 
 
603
 
    if (is_wide_mode)
604
 
    {
605
 
      thumb_view.set_columns (1);
606
 
      thumb_nav.set_vertical (true);
607
 
      if (thumbnails_bottom.get_child () != null)
608
 
      {
609
 
        thumbnails_bottom.remove (thumb_nav);
610
 
      }
611
 
      thumbnails_right.add (thumb_nav);
612
 
      thumbnails_right.show_all ();
613
 
      thumbnails_right.resize_children ();
614
 
      thumbnails_bottom.hide ();
615
 
    }
616
 
    else
617
 
    {
618
 
      thumb_view.set_columns (5000);
619
 
      thumb_nav.set_vertical (false);
620
 
      if (thumbnails_right.get_child () != null)
621
 
      {
622
 
        thumbnails_right.remove (thumb_nav);
623
 
      }
624
 
      thumbnails_bottom.add (thumb_nav);
625
 
      thumbnails_bottom.show_all ();
626
 
      thumbnails_bottom.resize_children ();
627
 
      thumbnails_right.hide ();
628
 
    }
629
 
 
630
 
    /* handy trick to keep the window to the desired size while not
631
 
     * requesting a fixed one. This way the window is resized to its
632
 
     * natural size (particularly with the constraints imposed by the
633
 
     * viewport, see above) but can still be shrinked down */
634
 
 
635
 
    Gtk.Requisition req;
636
 
    this.get_preferred_size(out req, out req);
637
 
    this.resize (req.width, req.height);
638
 
    viewport_widget.set_size_request (-1, -1);
639
 
  }
640
 
 
641
 
  /* To make sure that the layout manager manages the entire stage. */
642
 
  public void on_stage_resize (Clutter.Actor           actor,
643
 
                               Clutter.ActorBox        box,
644
 
                               Clutter.AllocationFlags flags)
645
 
  {
646
 
    this.viewport_layout.set_size (viewport.width, viewport.height);
647
 
    this.background_layer.set_size (viewport.width, viewport.height);
648
 
  }
649
 
 
650
 
  [CCode (instance_pos = -1)]
651
 
  public void on_countdown_toggle (ToggleAction action)
652
 
  {
653
 
    settings.set_boolean ("countdown", action.active);
654
 
  }
655
 
 
656
 
  private void finish_countdown_callback ()
657
 
  {
658
 
    if (action_cancelled == false)
659
 
    {
660
 
      string file_name = fileutil.get_new_media_filename (this.current_mode);
661
 
 
662
 
      if (settings.get_boolean ("flash"))
663
 
      {
664
 
        this.flash.fire ();
665
 
      }
666
 
      CanberraGtk.play_for_widget (this.main_vbox, 0,
667
 
                                   Canberra.PROP_EVENT_ID, "camera-shutter",
668
 
                                   Canberra.PROP_MEDIA_ROLE, "event",
669
 
                                   Canberra.PROP_EVENT_DESCRIPTION, _("Shutter sound"),
670
 
                                   null);
671
 
      this.camera.take_photo (file_name);
672
 
    }
673
 
 
674
 
    if (current_mode == MediaMode.PHOTO)
675
 
    {
676
 
      take_photo_action.sensitive = true;
677
 
      enable_mode_change ();
678
 
    }
679
 
  }
680
 
 
681
 
  Countdown current_countdown;
682
 
  public void take_photo ()
683
 
  {
684
 
    if (settings.get_boolean ("countdown"))
685
 
    {
686
 
      if (current_mode == MediaMode.PHOTO)
687
 
      {
688
 
        take_photo_action.sensitive = false;
689
 
        disable_mode_change ();
690
 
      }
691
 
 
692
 
      current_countdown = new Countdown (this.countdown_layer);
693
 
      current_countdown.start (finish_countdown_callback);
694
 
    }
695
 
    else
696
 
    {
697
 
      finish_countdown_callback ();
698
 
    }
699
 
  }
700
 
 
701
 
  private int  burst_count;
702
 
  private uint burst_callback_id;
703
 
 
704
 
  private bool burst_take_photo ()
705
 
  {
706
 
    if (is_bursting && burst_count < settings.get_int ("burst-repeat"))
707
 
    {
708
 
      this.take_photo ();
709
 
      burst_count++;
710
 
      return true;
711
 
    }
712
 
    else
713
 
    {
714
 
      toggle_photo_bursting (false);
715
 
      return false;
716
 
    }
717
 
  }
718
 
 
719
 
  private bool on_key_release (Gdk.EventKey event)
720
 
  {
721
 
    string key;
722
 
 
723
 
    key = Gdk.keyval_name (event.keyval);
724
 
    if (strcmp (key, "Escape") == 0)
725
 
    {
726
 
      if ((current_countdown != null && current_countdown.running) || is_bursting || is_recording)
727
 
      {
728
 
        action_cancelled = true;
729
 
        if (current_mode == MediaMode.PHOTO)
730
 
        {
731
 
          current_countdown.stop ();
732
 
          finish_countdown_callback ();
733
 
        }
734
 
        else
735
 
        if (current_mode == MediaMode.BURST)
736
 
        {
737
 
          toggle_photo_bursting (false);
738
 
        }
739
 
        else
740
 
        if (current_mode == MediaMode.VIDEO)
741
 
        {
742
 
          toggle_video_recording (false);
743
 
        }
744
 
        action_cancelled = false;
745
 
      }
746
 
      else
747
 
      if (is_effects_selector_active)
748
 
      {
749
 
        effects_toggle_action.set_active (false);
750
 
      }
751
 
    }
752
 
    return false;
753
 
  }
754
 
 
755
 
  public void toggle_video_recording (bool is_start)
756
 
  {
757
 
    if (is_start)
758
 
    {
759
 
      camera.start_video_recording (fileutil.get_new_media_filename (this.current_mode));
760
 
      take_action_button_label.label = "<b>" + _("Stop _Recording") + "</b>";
761
 
      take_action_button.tooltip_text = "Stop recording";
762
 
      take_action_button_image.set_from_stock (Gtk.Stock.MEDIA_STOP, Gtk.IconSize.BUTTON);
763
 
      this.is_recording = true;
764
 
      this.disable_mode_change ();
765
 
    }
766
 
    else
767
 
    {
768
 
      camera.stop_video_recording ();
769
 
      take_action_button_label.label = "<b>" + take_action_button.related_action.label + "</b>";
770
 
      take_action_button.tooltip_text = take_action_button.related_action.tooltip;
771
 
      take_action_button_image.set_from_stock (Gtk.Stock.MEDIA_RECORD, Gtk.IconSize.BUTTON);
772
 
      this.is_recording = false;
773
 
      this.enable_mode_change ();
774
 
    }
775
 
  }
776
 
 
777
 
  public void toggle_photo_bursting (bool is_start)
778
 
  {
779
 
    if (is_start)
780
 
    {
781
 
      is_bursting = true;
782
 
      this.disable_mode_change ();
783
 
      effects_toggle_action.sensitive = false;
784
 
      take_action_button_label.label  = "<b>" + _("Stop _Taking Pictures") + "</b>";
785
 
      take_action_button.tooltip_text = "Stop taking pictures";
786
 
      burst_take_photo ();
787
 
 
788
 
      /* 3500 ms is the approximate time for countdown animation to finish, so
789
 
         if burst-delay time is less than 3500 ms, just use 3500 ms. */
790
 
      if (((settings.get_int ("burst-delay") - 3500) < 1000) && settings.get_boolean ("countdown"))
791
 
      {
792
 
        burst_callback_id = GLib.Timeout.add (3500, burst_take_photo);
793
 
      }
794
 
      else
795
 
      {
796
 
        burst_callback_id = GLib.Timeout.add (settings.get_int ("burst-delay"), burst_take_photo);
797
 
      }
798
 
    }
799
 
    else
800
 
    {
801
 
      if (current_countdown != null && current_countdown.running)
802
 
        current_countdown.stop ();
803
 
 
804
 
      is_bursting = false;
805
 
      this.enable_mode_change ();
806
 
      take_action_button_label.label  = "<b>" + take_action_button.related_action.label + "</b>";
807
 
      take_action_button.tooltip_text = take_action_button.related_action.tooltip;
808
 
      burst_count = 0;
809
 
      fileutil.reset_burst ();
810
 
      GLib.Source.remove (burst_callback_id);
811
 
    }
812
 
  }
813
 
 
814
 
  [CCode (instance_pos = -1)]
815
 
  public void on_take_action (Gtk.Action action)
816
 
  {
817
 
    if (current_mode == MediaMode.PHOTO)
818
 
    {
819
 
      this.take_photo ();
820
 
    }
821
 
    else
822
 
    if (current_mode == MediaMode.VIDEO)
823
 
    {
824
 
      toggle_video_recording (!is_recording);
825
 
    }
826
 
    else
827
 
    if (current_mode == MediaMode.BURST)
828
 
    {
829
 
      toggle_photo_bursting (!is_bursting);
830
 
    }
831
 
  }
832
 
 
833
 
  [CCode (instance_pos = -1)]
834
 
  public void on_effects_toggle (Gtk.ToggleAction action)
835
 
  {
836
 
    toggle_effects_selector (action.active);
837
 
    take_photo_action.sensitive = !action.active;
838
 
    take_video_action.sensitive = !action.active;
839
 
    take_burst_action.sensitive = !action.active;
840
 
    photo_mode_action.sensitive = !action.active;
841
 
    video_mode_action.sensitive = !action.active;
842
 
    burst_mode_action.sensitive = !action.active;
843
 
  }
844
 
 
845
 
  public bool on_selected_effect_change (Clutter.Actor source,
846
 
                                         Clutter.ButtonEvent event)
847
 
  {
848
 
    selected_effect = source.get_data ("effect");
849
 
    camera.set_effect (selected_effect);
850
 
    settings.set_string ("selected-effect", selected_effect.name);
851
 
    effects_toggle_action.set_active (false);
852
 
    return false;
853
 
  }
854
 
 
855
 
  [CCode (instance_pos = -1)]
856
 
  public void on_prev_effects_page (Gtk.Action action)
857
 
  {
858
 
    if (current_effects_page != 0)
859
 
    {
860
 
      activate_effects_page (current_effects_page - 1);
861
 
    }
862
 
  }
863
 
 
864
 
  [CCode (instance_pos = -1)]
865
 
  public void on_next_effects_page (Gtk.Action action)
866
 
  {
867
 
    if (current_effects_page != (effects_manager.effects.size / EFFECTS_PER_PAGE))
868
 
    {
869
 
      activate_effects_page (current_effects_page + 1);
870
 
    }
871
 
  }
872
 
 
873
 
  private void activate_effects_page (int number)
874
 
  {
875
 
    if (!is_effects_selector_active)
876
 
      return;
877
 
    current_effects_page = number;
878
 
    if (viewport_layout.get_children ().index (current_effects_grid) != -1)
879
 
    {
880
 
      viewport_layout.remove ((Clutter.Actor) current_effects_grid);
881
 
    }
882
 
    current_effects_grid = effects_grids[number];
883
 
    current_effects_grid.set ("opacity", 0);
884
 
    viewport_layout.add ((Clutter.Actor) current_effects_grid);
885
 
    current_effects_grid.animate (Clutter.AnimationMode.LINEAR, 1000, "opacity", 255);
886
 
 
887
 
    for (int i = 0; i < effects_manager.effects.size; i++)
888
 
    {
889
 
      int           page_of_effect = i / EFFECTS_PER_PAGE;
890
 
      Cheese.Effect effect         = effects_manager.effects[i];
891
 
      if (page_of_effect == number)
892
 
      {
893
 
        if (!effect.is_preview_connected ())
894
 
        {
895
 
          Clutter.Texture texture = effect.get_data<Clutter.Texture> ("texture");
896
 
          camera.connect_effect_texture (effect, texture);
897
 
        }
898
 
        effect.enable_preview ();
899
 
      }
900
 
      else
901
 
      {
902
 
        if (effect.is_preview_connected ())
903
 
          effect.disable_preview ();
904
 
      }
905
 
    }
906
 
    setup_effects_page_switch_sensitivity ();
907
 
  }
908
 
 
909
 
  private void setup_effects_page_switch_sensitivity ()
910
 
  {
911
 
    effects_page_prev_action.sensitive = (is_effects_selector_active && current_effects_page != 0);
912
 
    effects_page_next_action.sensitive =
913
 
      (is_effects_selector_active && current_effects_page != effects_manager.effects.size / EFFECTS_PER_PAGE);
914
 
  }
915
 
 
916
 
  private void toggle_effects_selector (bool active)
917
 
  {
918
 
    is_effects_selector_active = active;
919
 
    if (active)
920
 
    {
921
 
      video_preview.hide ();
922
 
 
923
 
      if (effects_grids.size == 0)
924
 
      {
925
 
        error_layer.text = _("No effects found");
926
 
        error_layer.show ();
927
 
      }
928
 
      else
929
 
      {
930
 
        current_effects_grid.show ();
931
 
        activate_effects_page (current_effects_page);
932
 
      }
933
 
    }
934
 
    else
935
 
    {
936
 
      if (effects_grids.size == 0)
937
 
      {
938
 
        error_layer.hide ();
939
 
      }
940
 
      else
941
 
      {
942
 
        current_effects_grid.hide ();
943
 
      }
944
 
      video_preview.show ();
945
 
    }
946
 
 
947
 
    camera.toggle_effects_pipeline (active);
948
 
    setup_effects_page_switch_sensitivity ();
949
 
  }
950
 
 
951
 
  private void setup_effects_selector ()
952
 
  {
953
 
    if (current_effects_grid == null)
954
 
    {
955
 
      effects_manager = new EffectsManager ();
956
 
      effects_manager.load_effects ();
957
 
 
958
 
      /* Must initialize effects_grids before returning, as it is dereferenced later, bug 654671. */
959
 
      effects_grids = new ArrayList<Clutter.Box> ();
960
 
 
961
 
      if (effects_manager.effects.size == 0)
962
 
      {
963
 
        warning ("gnome-video-effects is not installed.");
964
 
        return;
965
 
      }
966
 
 
967
 
      for (int i = 0; i <= effects_manager.effects.size / EFFECTS_PER_PAGE; i++)
968
 
      {
969
 
        Clutter.TableLayout table_layout = new TableLayout ();
970
 
        Clutter.Box grid = new Clutter.Box (table_layout);
971
 
        effects_grids.add (grid);
972
 
        table_layout.set_column_spacing (10);
973
 
        table_layout.set_row_spacing (10);
974
 
      }
975
 
 
976
 
      for (int i = 0; i < effects_manager.effects.size; i++)
977
 
      {
978
 
        Effect            effect  = effects_manager.effects[i];
979
 
        Clutter.Texture   texture = new Clutter.Texture ();
980
 
        Clutter.BinLayout layout  = new Clutter.BinLayout (Clutter.BinAlignment.CENTER,
981
 
                                                           Clutter.BinAlignment.CENTER);
982
 
        Clutter.Box       box  = new Clutter.Box (layout);
983
 
        Clutter.Text      text = new Clutter.Text ();
984
 
        Clutter.Rectangle rect = new Clutter.Rectangle ();
985
 
 
986
 
        rect.opacity = 128;
987
 
        rect.color   = Clutter.Color.from_string ("black");
988
 
 
989
 
        texture.keep_aspect_ratio = true;
990
 
        box.pack ((Clutter.Actor) texture, null, null);
991
 
        box.reactive = true;
992
 
        box.set_data ("effect", effect);
993
 
        effect.set_data ("texture", texture);
994
 
 
995
 
        box.button_release_event.connect (on_selected_effect_change);
996
 
 
997
 
        text.text  = effect.name;
998
 
        text.color = Clutter.Color.from_string ("white");
999
 
 
1000
 
        rect.height = text.height + 5;
1001
 
        box.pack ((Clutter.Actor) rect,
1002
 
                  "x-align", Clutter.BinAlignment.FILL,
1003
 
                  "y-align", Clutter.BinAlignment.END, null);
1004
 
 
1005
 
        box.pack ((Clutter.Actor) text,
1006
 
                  "x-align", Clutter.BinAlignment.CENTER,
1007
 
                  "y-align", Clutter.BinAlignment.END, null);
1008
 
 
1009
 
        Clutter.TableLayout table_layout = (Clutter.TableLayout) effects_grids[i / EFFECTS_PER_PAGE].layout_manager;
1010
 
        table_layout.pack ((Clutter.Actor) box,
1011
 
                           (i % EFFECTS_PER_PAGE) % 3,
1012
 
                           (i % EFFECTS_PER_PAGE) / 3);
1013
 
        table_layout.set_expand (box, false, false);
1014
 
      }
1015
 
 
1016
 
      setup_effects_page_switch_sensitivity ();
1017
 
      current_effects_grid = effects_grids[0];
1018
 
    }
1019
 
  }
1020
 
 
1021
 
  private Gee.HashMap<string, bool> action_sensitivities;
1022
 
  public void toggle_camera_actions_sensitivities (bool active)
1023
 
  {
1024
 
    is_camera_actions_sensitive = active;
1025
 
    if (active)
1026
 
    {
1027
 
      foreach (string key in action_sensitivities.keys)
1028
 
      {
1029
 
        Gtk.Action action = (Gtk.Action)gtk_builder.get_object (key);
1030
 
        action.sensitive = action_sensitivities.get (key);
1031
 
      }
1032
 
    }
1033
 
    else
1034
 
    {
1035
 
      action_sensitivities = new HashMap<string, bool> (GLib.str_hash);
1036
 
      GLib.SList<weak GLib.Object> objects = gtk_builder.get_objects ();
1037
 
      foreach (GLib.Object obj in objects)
1038
 
      {
1039
 
        if (obj is Gtk.Action)
1040
 
        {
1041
 
          Gtk.Action action = (Gtk.Action)obj;
1042
 
          action_sensitivities.set (action.name, action.sensitive);
1043
 
        }
1044
 
      }
1045
 
 
1046
 
      /* Keep only these actions sensitive. */
1047
 
      string [] active_actions = { "cheese_action",
1048
 
                                    "edit_action",
1049
 
                                    "help_action",
1050
 
                                    "quit",
1051
 
                                    "help_contents",
1052
 
                                    "about",
1053
 
                                    "open",
1054
 
                                    "save_as",
1055
 
                                    "move_to_trash",
1056
 
                                    "delete",
1057
 
                                    "move_all_to_trash"};
1058
 
 
1059
 
      /* Gross hack because Vala's `in` operator doesn't really work */
1060
 
      bool flag;
1061
 
      foreach (GLib.Object obj in objects)
1062
 
      {
1063
 
        flag = false;
1064
 
        if (obj is Gtk.Action)
1065
 
        {
1066
 
          Gtk.Action action = (Gtk.Action)obj;
1067
 
          foreach (string s in active_actions)
1068
 
          {
1069
 
            if (action.name == s)
1070
 
            {
1071
 
              flag = true;
1072
 
            }
1073
 
          }
1074
 
          if (!flag)
1075
 
            ((Gtk.Action)obj).sensitive = false;
1076
 
        }
1077
 
      }
1078
 
    }
1079
 
  }
1080
 
 
1081
 
  private void camera_state_changed (Gst.State new_state)
1082
 
  {
1083
 
    if (new_state == Gst.State.PLAYING)
1084
 
    {
1085
 
      if (!is_camera_actions_sensitive)
1086
 
        toggle_camera_actions_sensitivities (true);
1087
 
 
1088
 
      Effect effect = effects_manager.get_effect (settings.get_string ("selected-effect"));
1089
 
      if (effect != null)
1090
 
        camera.set_effect (effect);
1091
 
    }
1092
 
  }
1093
 
 
1094
 
  public void set_startup_wide_mode ()
1095
 
  {
1096
 
    if (is_wide_mode)
1097
 
    {
1098
 
      /* Cheese was already in wide mode, avoid setting it again. */
1099
 
      return;
1100
 
    }
1101
 
 
1102
 
    is_command_line_startup = true;
1103
 
    wide_mode_action.set_active (true);
1104
 
    is_command_line_startup = false;
1105
 
  }
1106
 
 
1107
 
  public void set_startup_fullscreen_mode ()
1108
 
  {
1109
 
    is_command_line_startup = true;
1110
 
    fullscreen_action.set_active (true);
1111
 
    is_command_line_startup = false;
1112
 
  }
1113
 
 
1114
 
  public void setup_ui ()
1115
 
  {
1116
 
    gtk_builder     = new Gtk.Builder ();
1117
 
    clutter_builder = new Clutter.Script ();
1118
 
    fileutil        = new FileUtil ();
1119
 
    flash           = new Flash (this);
1120
 
    settings        = new GLib.Settings ("org.gnome.Cheese");
1121
 
 
1122
 
    try {
1123
 
      gtk_builder.add_from_file (GLib.Path.build_filename (Config.PACKAGE_DATADIR, "cheese-actions.ui"));
1124
 
      gtk_builder.add_from_file (GLib.Path.build_filename (Config.PACKAGE_DATADIR, "cheese-about.ui"));
1125
 
      gtk_builder.add_from_file (GLib.Path.build_filename (Config.PACKAGE_DATADIR, "cheese-main-window.ui"));
1126
 
      gtk_builder.connect_signals (this);
1127
 
 
1128
 
      clutter_builder.load_from_file (GLib.Path.build_filename (Config.PACKAGE_DATADIR, "cheese-viewport.json"));
1129
 
    } catch (Error err)
1130
 
    {
1131
 
      error ("Error: %s", err.message);
1132
 
    }
1133
 
 
1134
 
    main_vbox                         = (Gtk.VBox)gtk_builder.get_object ("mainbox_normal");
1135
 
    thumbnails                        = (Gtk.Widget)gtk_builder.get_object ("thumbnails");
1136
 
    viewport_widget                   = (GtkClutter.Embed)gtk_builder.get_object ("viewport");
1137
 
    viewport                          = (Clutter.Stage)viewport_widget.get_stage ();
1138
 
    thumbnails_right                  = (Gtk.Alignment)gtk_builder.get_object ("thumbnails_right");
1139
 
    thumbnails_bottom                 = (Gtk.Alignment)gtk_builder.get_object ("thumbnails_bottom");
1140
 
    menubar                           = (Gtk.MenuBar)gtk_builder.get_object ("main_menubar");
1141
 
    leave_fullscreen_button_container = (Gtk.HBox)gtk_builder.get_object ("leave_fullscreen_button_bin");
1142
 
    photo_toggle_button               = (Gtk.ToggleButton)gtk_builder.get_object ("photo_toggle_button");
1143
 
    video_toggle_button               = (Gtk.ToggleButton)gtk_builder.get_object ("video_toggle_button");
1144
 
    burst_toggle_button               = (Gtk.ToggleButton)gtk_builder.get_object ("burst_toggle_button");
1145
 
    take_action_button                = (Gtk.Button)gtk_builder.get_object ("take_action_button");
1146
 
    take_action_button_label          = (Gtk.Label)gtk_builder.get_object ("take_action_button_internal_label");
1147
 
    take_action_button_image          = (Gtk.Image)gtk_builder.get_object ("take_action_button_internal_image");
1148
 
    effects_toggle_button             = (Gtk.ToggleButton)gtk_builder.get_object ("effects_toggle_button");
1149
 
    leave_fullscreen_button           = (Gtk.Button)gtk_builder.get_object ("leave_fullscreen_button");
1150
 
    buttons_area                      = (Gtk.HBox)gtk_builder.get_object ("buttons_area");
1151
 
    thumbnail_popup                   = (Gtk.Menu)gtk_builder.get_object ("thumbnail_popup");
1152
 
 
1153
 
    take_photo_action        = (Gtk.Action)gtk_builder.get_object ("take_photo");
1154
 
    take_video_action        = (Gtk.Action)gtk_builder.get_object ("take_video");
1155
 
    take_burst_action        = (Gtk.Action)gtk_builder.get_object ("take_burst");
1156
 
    photo_mode_action        = (Gtk.Action)gtk_builder.get_object ("photo_mode");
1157
 
    video_mode_action        = (Gtk.Action)gtk_builder.get_object ("video_mode");
1158
 
    burst_mode_action        = (Gtk.Action)gtk_builder.get_object ("burst_mode");
1159
 
    effects_toggle_action    = (Gtk.ToggleAction)gtk_builder.get_object ("effects_toggle");
1160
 
    countdown_action         = (Gtk.Action)gtk_builder.get_object ("countdown");
1161
 
    wide_mode_action         = (Gtk.ToggleAction)gtk_builder.get_object ("wide_mode");
1162
 
    fullscreen_action        = (Gtk.ToggleAction)gtk_builder.get_object ("fullscreen");
1163
 
    effects_page_next_action = (Gtk.Action)gtk_builder.get_object ("effects_page_next");
1164
 
    effects_page_prev_action = (Gtk.Action)gtk_builder.get_object ("effects_page_prev");
1165
 
 
1166
 
    /* Array contains all 'buttons', for easier manipulation
1167
 
     * IMPORTANT: IF ANOTHER BUTTON IS ADDED UNDER THE VIEWPORT, ADD IT TO THIS ARRAY */
1168
 
    buttons = {photo_toggle_button,
1169
 
               video_toggle_button,
1170
 
               burst_toggle_button,
1171
 
               take_action_button,
1172
 
               effects_toggle_button,
1173
 
               leave_fullscreen_button};
1174
 
 
1175
 
    video_preview           = (Clutter.Texture)clutter_builder.get_object ("video_preview");
1176
 
    viewport_layout         = (Clutter.Box)clutter_builder.get_object ("viewport_layout");
1177
 
    viewport_layout_manager = (Clutter.BinLayout)clutter_builder.get_object ("viewport_layout_manager");
1178
 
    countdown_layer         = (Clutter.Text)clutter_builder.get_object ("countdown_layer");
1179
 
    background_layer        = (Clutter.Rectangle)clutter_builder.get_object ("background");
1180
 
    error_layer             = (Clutter.Text)clutter_builder.get_object ("error_layer");
1181
 
 
1182
 
    video_preview.keep_aspect_ratio = true;
1183
 
    video_preview.request_mode      = Clutter.RequestMode.HEIGHT_FOR_WIDTH;
1184
 
    viewport.add_actor (background_layer);
1185
 
    viewport_layout.set_layout_manager (viewport_layout_manager);
1186
 
 
1187
 
    viewport.add_actor (viewport_layout);
1188
 
 
1189
 
    viewport.allocation_changed.connect (on_stage_resize);
1190
 
 
1191
 
    thumb_view = new Cheese.ThumbView ();
1192
 
    thumb_nav  = new Eog.ThumbNav (thumb_view, false);
1193
 
 
1194
 
    Gtk.CssProvider css;
1195
 
    try
1196
 
    {
1197
 
      css = new Gtk.CssProvider();
1198
 
      css.load_from_path (GLib.Path.build_filename (Config.PACKAGE_DATADIR, "cheese.css"));
1199
 
    }
1200
 
    catch (Error e)
1201
 
    {
1202
 
      stdout.printf ("Error: %s\n", e.message);
1203
 
    }
1204
 
 
1205
 
    Gtk.StyleContext context;
1206
 
    context = thumb_view.get_style_context ();
1207
 
    screen = Gdk.Screen.get_default();
1208
 
    context.add_provider_for_screen (screen, css, 600);
1209
 
 
1210
 
    thumb_view.button_press_event.connect (on_thumbnail_mouse_button_press);
1211
 
 
1212
 
    this.add (main_vbox);
1213
 
    main_vbox.show_all ();
1214
 
 
1215
 
    /* needed for the sizing tricks in set_wide_mode (allocation is 0
1216
 
     * if the widget is not realized */
1217
 
    viewport_widget.realize ();
1218
 
 
1219
 
    /* call set_active instead of our set_wide_mode so that the toggle
1220
 
     * action state is updated */
1221
 
    wide_mode_action.set_active (settings.get_boolean ("wide-mode"));
1222
 
 
1223
 
    /* apparently set_active doesn't emit toggled nothing has
1224
 
     * changed, do it manually */
1225
 
    if (!settings.get_boolean ("wide-mode"))
1226
 
      wide_mode_action.toggled ();
1227
 
 
1228
 
    set_mode (MediaMode.PHOTO);
1229
 
    setup_effects_selector ();
1230
 
 
1231
 
    toggle_camera_actions_sensitivities (false);
1232
 
 
1233
 
    this.key_release_event.connect (on_key_release);
1234
 
 
1235
 
    if (settings.get_boolean ("fullscreen"))
1236
 
      fullscreen_action.active = true;
1237
 
  }
1238
 
 
1239
 
  public void setup_camera (string ? uri)
1240
 
  {
1241
 
    string device;
1242
 
    double value;
1243
 
 
1244
 
    if (uri != null && uri.length > 0)
1245
 
      device = uri;
1246
 
    else
1247
 
      device = settings.get_string ("camera");
1248
 
 
1249
 
    camera = new Camera (video_preview,
1250
 
                         device,
1251
 
                         settings.get_int ("photo-x-resolution"),
1252
 
                         settings.get_int ("photo-y-resolution"));
1253
 
    try {
1254
 
      camera.setup (device);
1255
 
    }
1256
 
    catch (Error err)
1257
 
    {
1258
 
      video_preview.hide ();
1259
 
      warning ("Error: %s\n", err.message);
1260
 
      error_layer.text = err.message;
1261
 
      error_layer.show ();
1262
 
 
1263
 
      toggle_camera_actions_sensitivities (false);
1264
 
      return;
1265
 
    }
1266
 
 
1267
 
    value = settings.get_double ("brightness");
1268
 
    if (value != 0.0)
1269
 
      camera.set_balance_property ("brightness", value);
1270
 
 
1271
 
    value = settings.get_double ("contrast");
1272
 
    if (value != 1.0)
1273
 
      camera.set_balance_property ("contrast", value);
1274
 
 
1275
 
    value = settings.get_double ("hue");
1276
 
    if (value != 0.0)
1277
 
      camera.set_balance_property ("hue", value);
1278
 
 
1279
 
    value = settings.get_double ("saturation");
1280
 
    if (value != 1.0)
1281
 
      camera.set_balance_property ("saturation", value);
1282
 
 
1283
 
    camera.state_flags_changed.connect (camera_state_changed);
1284
 
    camera.play ();
1285
 
  }
1286
 
  public void start_thumbview_monitors ()
1287
 
  {
1288
 
    thumb_view.start_monitoring_video_path (fileutil.get_video_path ());
1289
 
    thumb_view.start_monitoring_photo_path (fileutil.get_photo_path ());
1290
 
  }
1291
 
}