~wongchiachen/ubuntu/precise/totem/hey_about_dialog

« back to all changes in this revision

Viewing changes to .pc/02_lpi.patch/src/totem-menu.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2011-05-20 16:38:02 UTC
  • mfrom: (1.11.13 upstream) (2.1.17 experimental)
  • Revision ID: james.westby@ubuntu.com-20110520163802-p3lohdmfvws2jqeo
Tags: 3.0.1-0ubuntu1
* Resynchronize on Debian, remaining diffs:
* debian/control.in:
  - use suggests rather than recommends for universe gstreamer components
  - add totem-plugins-extra for the components which have depends in universe
  - add build-depends on gnome-common, dh-autoreconf, 
    liblaunchpad-intrgration-3.0-dev, hardening-wrapper
  - drop build-depends on libepc-ui-dev, python-feedparser, xulrunner-dev,
    libtracker-sparql-0.10-dev
  - add XB-Npp-Description and XB-Npp-Filename header to the 
    totem-mozilla package to improve ubufox/ubuntu plugin db integration 
  - change refences from Iceweasel to Firefox
  - recommends gnome-icon-theme-symbolic rather than depending on it
  - list firefox as a totem-mozilla recommends before epiphany-browser
  - libtotem replaces totem (<< 3.0.1-1) for ppa upgrades
* debian/totem-common.install:
  - Install apport hook
* debian/totem-plugins-extra.install:
  - Plugins split out ouf totem-plugins
* debian/totem-plugins.install:    
  - Move some plugins to totem-plugins-extra
* debian/totem.preinst:
  - No longer required as Lucid has been released
* debian/patches/01_fake_keypresses.patch:
  - dropped it's an old workaround and should not be required
* debian/patches/02_lpi.patch:
  - Launchpad integration
* debian/patches/03_default_options.patch: 
  - enable the youtube option by default
* debian/patches/70_bbc_plugin.patch:
  - bbc content viewer, needs to be fixed for the new version
* debian/source_totem.py:
  - ubuntu apport debugging
* debian/rules:
  - run autoreconf on build
* debian/watch:
  - Watch for unstable versions

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* totem-menu.c
 
2
 
 
3
   Copyright (C) 2004-2005 Bastien Nocera
 
4
 
 
5
   The Gnome Library is free software; you can redistribute it and/or
 
6
   modify it under the terms of the GNU Library General Public License as
 
7
   published by the Free Software Foundation; either version 2 of the
 
8
   License, or (at your option) any later version.
 
9
 
 
10
   The Gnome Library is distributed in the hope that it will be useful,
 
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
   Library General Public License for more details.
 
14
 
 
15
   You should have received a copy of the GNU Library General Public
 
16
   License along with the Gnome Library; see the file COPYING.LIB.  If not,
 
17
   write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
18
   Boston, MA 02110-1301  USA.
 
19
 
 
20
   Author: Bastien Nocera <hadess@hadess.net>
 
21
 */
 
22
 
 
23
#include "config.h"
 
24
 
 
25
#include <gtk/gtk.h>
 
26
#include <glib/gi18n.h>
 
27
#include <gst/tag/tag.h>
 
28
#include <string.h>
 
29
#include <libpeas-gtk/peas-gtk-plugin-manager.h>
 
30
 
 
31
#include "totem-menu.h"
 
32
#include "totem.h"
 
33
#include "totem-interface.h"
 
34
#include "totem-private.h"
 
35
#include "totem-sidebar.h"
 
36
#include "totem-statusbar.h"
 
37
#include "bacon-video-widget.h"
 
38
#include "totem-uri.h"
 
39
 
 
40
#include "totem-profile.h"
 
41
 
 
42
#define TOTEM_MAX_RECENT_ITEM_LEN 40
 
43
 
 
44
/* Callback functions for GtkBuilder */
 
45
G_MODULE_EXPORT void open_action_callback (GtkAction *action, Totem *totem);
 
46
G_MODULE_EXPORT void open_location_action_callback (GtkAction *action, Totem *totem);
 
47
G_MODULE_EXPORT void eject_action_callback (GtkAction *action, Totem *totem);
 
48
G_MODULE_EXPORT void properties_action_callback (GtkAction *action, Totem *totem);
 
49
G_MODULE_EXPORT void play_action_callback (GtkAction *action, Totem *totem);
 
50
G_MODULE_EXPORT void quit_action_callback (GtkAction *action, Totem *totem);
 
51
G_MODULE_EXPORT void preferences_action_callback (GtkAction *action, Totem *totem);
 
52
G_MODULE_EXPORT void fullscreen_action_callback (GtkAction *action, Totem *totem);
 
53
G_MODULE_EXPORT void zoom_1_2_action_callback (GtkAction *action, Totem *totem);
 
54
G_MODULE_EXPORT void zoom_1_1_action_callback (GtkAction *action, Totem *totem);
 
55
G_MODULE_EXPORT void zoom_2_1_action_callback (GtkAction *action, Totem *totem);
 
56
G_MODULE_EXPORT void zoom_in_action_callback (GtkAction *action, Totem *totem);
 
57
G_MODULE_EXPORT void zoom_reset_action_callback (GtkAction *action, Totem *totem);
 
58
G_MODULE_EXPORT void zoom_out_action_callback (GtkAction *action, Totem *totem);
 
59
G_MODULE_EXPORT void next_angle_action_callback (GtkAction *action, Totem *totem);
 
60
G_MODULE_EXPORT void dvd_root_menu_action_callback (GtkAction *action, Totem *totem);
 
61
G_MODULE_EXPORT void dvd_title_menu_action_callback (GtkAction *action, Totem *totem);
 
62
G_MODULE_EXPORT void dvd_audio_menu_action_callback (GtkAction *action, Totem *totem);
 
63
G_MODULE_EXPORT void dvd_angle_menu_action_callback (GtkAction *action, Totem *totem);
 
64
G_MODULE_EXPORT void dvd_chapter_menu_action_callback (GtkAction *action, Totem *totem);
 
65
G_MODULE_EXPORT void next_chapter_action_callback (GtkAction *action, Totem *totem);
 
66
G_MODULE_EXPORT void previous_chapter_action_callback (GtkAction *action, Totem *totem);
 
67
G_MODULE_EXPORT void skip_forward_action_callback (GtkAction *action, Totem *totem);
 
68
G_MODULE_EXPORT void skip_backwards_action_callback (GtkAction *action, Totem *totem);
 
69
G_MODULE_EXPORT void volume_up_action_callback (GtkAction *action, Totem *totem);
 
70
G_MODULE_EXPORT void volume_down_action_callback (GtkAction *action, Totem *totem);
 
71
G_MODULE_EXPORT void contents_action_callback (GtkAction *action, Totem *totem);
 
72
G_MODULE_EXPORT void about_action_callback (GtkAction *action, Totem *totem);
 
73
G_MODULE_EXPORT void plugins_action_callback (GtkAction *action, Totem *totem);
 
74
G_MODULE_EXPORT void repeat_mode_action_callback (GtkToggleAction *action, Totem *totem);
 
75
G_MODULE_EXPORT void shuffle_mode_action_callback (GtkToggleAction *action, Totem *totem);
 
76
G_MODULE_EXPORT void show_controls_action_callback (GtkToggleAction *action, Totem *totem);
 
77
G_MODULE_EXPORT void show_sidebar_action_callback (GtkToggleAction *action, Totem *totem);
 
78
G_MODULE_EXPORT void aspect_ratio_changed_callback (GtkRadioAction *action, GtkRadioAction *current, Totem *totem);
 
79
G_MODULE_EXPORT void select_subtitle_action_callback (GtkAction *action, Totem *totem);
 
80
G_MODULE_EXPORT void clear_playlist_action_callback (GtkAction *action, Totem *totem);
 
81
 
 
82
/* Helper function to escape underscores in labels
 
83
 * before putting them in menu items */
 
84
static char *
 
85
escape_label_for_menu (const char *name)
 
86
{
 
87
        char *new, **a;
 
88
 
 
89
        a = g_strsplit (name, "_", -1);
 
90
        new = g_strjoinv ("__", a);
 
91
        g_strfreev (a);
 
92
 
 
93
        return new;
 
94
}
 
95
 
 
96
/* Subtitle and language menus */
 
97
static void
 
98
totem_g_list_deep_free (GList *list)
 
99
{
 
100
        GList *l;
 
101
 
 
102
        for (l = list; l != NULL; l = l->next)
 
103
                g_free (l->data);
 
104
        g_list_free (list);
 
105
}
 
106
 
 
107
static void
 
108
subtitles_changed_callback (GtkRadioAction *action, GtkRadioAction *current,
 
109
                Totem *totem)
 
110
{
 
111
        int rank;
 
112
 
 
113
        rank = gtk_radio_action_get_current_value (current);
 
114
 
 
115
        bacon_video_widget_set_subtitle (totem->bvw, rank);
 
116
}
 
117
 
 
118
 
 
119
static void
 
120
languages_changed_callback (GtkRadioAction *action, GtkRadioAction *current,
 
121
                Totem *totem)
 
122
{
 
123
        int rank;
 
124
 
 
125
        rank = gtk_radio_action_get_current_value (current);
 
126
 
 
127
        bacon_video_widget_set_language (totem->bvw, rank);
 
128
}
 
129
 
 
130
static GtkAction *
 
131
add_lang_action (Totem *totem, GtkActionGroup *action_group, guint ui_id,
 
132
                const char **paths, const char *prefix, const char *lang, 
 
133
                int lang_id, int lang_index, GSList **group)
 
134
{
 
135
        const char *full_lang;
 
136
        char *label;
 
137
        char *name;
 
138
        GtkAction *action;
 
139
        guint i;
 
140
 
 
141
        full_lang = gst_tag_get_language_name (lang);
 
142
 
 
143
        if (lang_index > 1) {
 
144
                char *num_lang;
 
145
 
 
146
                num_lang = g_strdup_printf ("%s #%u",
 
147
                                            full_lang ? full_lang : lang,
 
148
                                            lang_index);
 
149
                label = escape_label_for_menu (num_lang);
 
150
                g_free (num_lang);
 
151
        } else {
 
152
                label = escape_label_for_menu (full_lang ? full_lang : lang);
 
153
        }
 
154
 
 
155
        name = g_strdup_printf ("%s-%d", prefix, lang_id);
 
156
 
 
157
        action = g_object_new (GTK_TYPE_RADIO_ACTION,
 
158
                               "name", name,
 
159
                               "label", label,
 
160
                               "value", lang_id,
 
161
                               NULL);
 
162
        g_free (label);
 
163
 
 
164
        gtk_radio_action_set_group (GTK_RADIO_ACTION (action), *group);
 
165
        *group = gtk_radio_action_get_group (GTK_RADIO_ACTION (action));
 
166
        gtk_action_group_add_action (action_group, action);
 
167
        g_object_unref (action);
 
168
        for (i = 0; paths[i] != NULL; i++) {
 
169
                gtk_ui_manager_add_ui (totem->ui_manager, ui_id,
 
170
                                       paths[i], name, name, GTK_UI_MANAGER_MENUITEM, FALSE);
 
171
        }
 
172
        g_free (name);
 
173
 
 
174
        return action;
 
175
}
 
176
 
 
177
static GtkAction *
 
178
create_lang_actions (Totem *totem, GtkActionGroup *action_group, guint ui_id,
 
179
                const char **paths, const char *prefix, GList *list,
 
180
                gboolean is_lang)
 
181
{
 
182
        GtkAction *action = NULL;
 
183
        unsigned int i, *hash_value;
 
184
        GList *l;
 
185
        GSList *group = NULL;
 
186
        GHashTable *lookup;
 
187
        char *action_data;
 
188
 
 
189
        if (is_lang == FALSE) {
 
190
                add_lang_action (totem, action_group, ui_id, paths, prefix,
 
191
                                /* Translators: an entry in the "Languages" menu, used to choose the audio language of a DVD */
 
192
                                _("None"), -2, 0, &group);
 
193
        }
 
194
 
 
195
        action = add_lang_action (totem, action_group, ui_id, paths, prefix,
 
196
                                  /* Translators: an entry in the "Languages" menu, used to choose the audio language of a DVD */
 
197
                                  C_("Language", "Auto"), -1, 0, &group);
 
198
 
 
199
        i = 0;
 
200
        lookup = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
 
201
 
 
202
        for (l = list; l != NULL; l = l->next)
 
203
        {
 
204
                guint num;
 
205
 
 
206
                hash_value = g_hash_table_lookup (lookup, l->data);
 
207
                if (hash_value == NULL) {
 
208
                        num = 0;
 
209
                        action_data = g_strdup (l->data);
 
210
                        g_hash_table_insert (lookup, l->data, GINT_TO_POINTER (1));
 
211
                } else {
 
212
                        num = GPOINTER_TO_INT (hash_value);
 
213
                        action_data = g_strdup (l->data);
 
214
                        g_hash_table_replace (lookup, l->data, GINT_TO_POINTER (num + 1));
 
215
                }
 
216
 
 
217
                add_lang_action (totem, action_group, ui_id, paths, prefix,
 
218
                                 action_data, i, num + 1, &group);
 
219
                g_free (action_data);
 
220
                i++;
 
221
        }
 
222
 
 
223
        g_hash_table_destroy (lookup);
 
224
 
 
225
        return action;
 
226
}
 
227
 
 
228
static gboolean
 
229
totem_sublang_equal_lists (GList *orig, GList *new)
 
230
{
 
231
        GList *o, *n;
 
232
        gboolean retval;
 
233
 
 
234
        if ((orig == NULL && new != NULL) || (orig != NULL && new == NULL))
 
235
                return FALSE;
 
236
        if (orig == NULL && new == NULL)
 
237
                return TRUE;
 
238
 
 
239
        if (g_list_length (orig) != g_list_length (new))
 
240
                return FALSE;
 
241
 
 
242
        retval = TRUE;
 
243
        o = orig;
 
244
        n = new;
 
245
        while (o != NULL && n != NULL && retval != FALSE)
 
246
        {
 
247
                if (g_str_equal (o->data, n->data) == FALSE)
 
248
                        retval = FALSE;
 
249
                o = g_list_next (o);
 
250
                n = g_list_next (n);
 
251
        }
 
252
 
 
253
        return retval;
 
254
}
 
255
 
 
256
static void
 
257
totem_languages_update (Totem *totem, GList *list)
 
258
{
 
259
        GtkAction *action;
 
260
        const char *paths[3] = { "/tmw-menubar/sound/languages/placeholder", "/totem-main-popup/popup-languages/placeholder", NULL };
 
261
        int current;
 
262
 
 
263
        /* Remove old UI */
 
264
        gtk_ui_manager_remove_ui (totem->ui_manager, totem->languages_ui_id);
 
265
        gtk_ui_manager_ensure_update (totem->ui_manager);
 
266
 
 
267
        /* Create new ActionGroup */
 
268
        if (totem->languages_action_group) {
 
269
                gtk_ui_manager_remove_action_group (totem->ui_manager,
 
270
                                totem->languages_action_group);
 
271
                g_object_unref (totem->languages_action_group);
 
272
        }
 
273
        totem->languages_action_group = gtk_action_group_new ("languages-action-group");
 
274
        gtk_ui_manager_insert_action_group (totem->ui_manager,
 
275
                        totem->languages_action_group, -1);
 
276
 
 
277
        if (list != NULL) {
 
278
                action = create_lang_actions (totem, totem->languages_action_group,
 
279
                                totem->languages_ui_id,
 
280
                                paths,
 
281
                                "languages", list, TRUE);
 
282
                gtk_ui_manager_ensure_update (totem->ui_manager);
 
283
 
 
284
                current = bacon_video_widget_get_language (totem->bvw);
 
285
                gtk_radio_action_set_current_value (GTK_RADIO_ACTION (action),
 
286
                                current);
 
287
                g_signal_connect (G_OBJECT (action), "changed",
 
288
                                G_CALLBACK (languages_changed_callback), totem);
 
289
        }
 
290
 
 
291
        totem_g_list_deep_free (totem->language_list);
 
292
        totem->language_list = list;
 
293
}
 
294
 
 
295
static void
 
296
totem_subtitles_update (Totem *totem, GList *list)
 
297
{
 
298
        GtkAction *action;
 
299
        int current;
 
300
        const char *paths[3] = { "/tmw-menubar/view/subtitles/placeholder", "/totem-main-popup/popup-subtitles/placeholder", NULL };
 
301
 
 
302
        /* Remove old UI */
 
303
        gtk_ui_manager_remove_ui (totem->ui_manager, totem->subtitles_ui_id);
 
304
        gtk_ui_manager_ensure_update (totem->ui_manager);
 
305
 
 
306
        /* Create new ActionGroup */
 
307
        if (totem->subtitles_action_group) {
 
308
                gtk_ui_manager_remove_action_group (totem->ui_manager,
 
309
                                totem->subtitles_action_group);
 
310
                g_object_unref (totem->subtitles_action_group);
 
311
        }
 
312
        totem->subtitles_action_group = gtk_action_group_new ("subtitles-action-group");
 
313
        gtk_ui_manager_insert_action_group (totem->ui_manager,
 
314
                        totem->subtitles_action_group, -1);
 
315
 
 
316
 
 
317
        if (list != NULL) {
 
318
                action = create_lang_actions (totem, totem->subtitles_action_group,
 
319
                                totem->subtitles_ui_id,
 
320
                                paths,
 
321
                                "subtitles", list, FALSE);
 
322
                gtk_ui_manager_ensure_update (totem->ui_manager);
 
323
 
 
324
                current = bacon_video_widget_get_subtitle (totem->bvw);
 
325
                gtk_radio_action_set_current_value (GTK_RADIO_ACTION (action),
 
326
                                current);
 
327
                g_signal_connect (G_OBJECT (action), "changed",
 
328
                                G_CALLBACK (subtitles_changed_callback), totem);
 
329
        }
 
330
 
 
331
        totem_g_list_deep_free (totem->subtitles_list);
 
332
        totem->subtitles_list = list;
 
333
}
 
334
 
 
335
void
 
336
totem_sublang_update (Totem *totem)
 
337
{
 
338
        GList *list;
 
339
 
 
340
        list = bacon_video_widget_get_languages (totem->bvw);
 
341
        if (totem_sublang_equal_lists (totem->language_list, list) == TRUE) {
 
342
                totem_g_list_deep_free (list);
 
343
        } else {
 
344
                totem_languages_update (totem, list);
 
345
        }
 
346
 
 
347
        list = bacon_video_widget_get_subtitles (totem->bvw);
 
348
        if (totem_sublang_equal_lists (totem->subtitles_list, list) == TRUE) {
 
349
                totem_g_list_deep_free (list);
 
350
        } else {
 
351
                totem_subtitles_update (totem, list);
 
352
        }
 
353
}
 
354
 
 
355
void
 
356
totem_sublang_exit (Totem *totem)
 
357
{
 
358
        totem_g_list_deep_free (totem->subtitles_list);
 
359
        totem_g_list_deep_free (totem->language_list);
 
360
}
 
361
 
 
362
/* Recent files */
 
363
static void
 
364
connect_proxy_cb (GtkActionGroup *action_group,
 
365
                  GtkAction *action,
 
366
                  GtkWidget *proxy,
 
367
                  gpointer data)
 
368
{
 
369
        GtkLabel *label;
 
370
 
 
371
        if (!GTK_IS_MENU_ITEM (proxy))
 
372
                return;
 
373
 
 
374
        label = GTK_LABEL (gtk_bin_get_child (GTK_BIN (proxy)));
 
375
 
 
376
        gtk_label_set_ellipsize (label, PANGO_ELLIPSIZE_MIDDLE);
 
377
        gtk_label_set_max_width_chars (label,TOTEM_MAX_RECENT_ITEM_LEN);
 
378
}
 
379
 
 
380
static void
 
381
on_recent_file_item_activated (GtkAction *action,
 
382
                               Totem *totem)
 
383
{
 
384
        GtkRecentInfo *recent_info;
 
385
        const gchar *uri, *display_name;
 
386
 
 
387
        recent_info = g_object_get_data (G_OBJECT (action), "recent-info");
 
388
        uri = gtk_recent_info_get_uri (recent_info);
 
389
        display_name = gtk_recent_info_get_display_name (recent_info);
 
390
 
 
391
        totem_add_to_playlist_and_play (totem, uri, display_name, FALSE);
 
392
}
 
393
 
 
394
static gint
 
395
totem_compare_recent_items (GtkRecentInfo *a, GtkRecentInfo *b)
 
396
{
 
397
        gboolean has_totem_a, has_totem_b;
 
398
 
 
399
        has_totem_a = gtk_recent_info_has_group (a, "Totem");
 
400
        has_totem_b = gtk_recent_info_has_group (b, "Totem");
 
401
 
 
402
        if (has_totem_a && has_totem_b) {
 
403
                time_t time_a, time_b;
 
404
 
 
405
                time_a = gtk_recent_info_get_modified (a);
 
406
                time_b = gtk_recent_info_get_modified (b);
 
407
 
 
408
                return (time_b - time_a);
 
409
        } else if (has_totem_a) {
 
410
                return -1;
 
411
        } else if (has_totem_b) {
 
412
                return 1;
 
413
        }
 
414
 
 
415
        return 0;
 
416
}
 
417
 
 
418
static void
 
419
totem_recent_manager_changed_callback (GtkRecentManager *recent_manager, Totem *totem)
 
420
{
 
421
        GList *items, *totem_items, *l;
 
422
        guint n_items = 0;
 
423
 
 
424
        if (totem->recent_ui_id != 0) {
 
425
                gtk_ui_manager_remove_ui (totem->ui_manager, totem->recent_ui_id);
 
426
                gtk_ui_manager_ensure_update (totem->ui_manager);
 
427
        }
 
428
 
 
429
        if (totem->recent_action_group) {
 
430
                gtk_ui_manager_remove_action_group (totem->ui_manager,
 
431
                                totem->recent_action_group);
 
432
        }
 
433
 
 
434
        totem->recent_action_group = gtk_action_group_new ("recent-action-group");
 
435
        g_signal_connect (totem->recent_action_group, "connect-proxy",
 
436
                          G_CALLBACK (connect_proxy_cb), NULL);
 
437
        gtk_ui_manager_insert_action_group (totem->ui_manager,
 
438
                        totem->recent_action_group, -1);
 
439
        g_object_unref (totem->recent_action_group);
 
440
 
 
441
        totem->recent_ui_id = gtk_ui_manager_new_merge_id (totem->ui_manager);
 
442
        items = gtk_recent_manager_get_items (recent_manager);
 
443
 
 
444
        /* Remove the non-Totem items */
 
445
        totem_items = NULL;
 
446
        for (l = items; l && l->data; l = l->next) {
 
447
                GtkRecentInfo *info;
 
448
 
 
449
                info = (GtkRecentInfo *) l->data;
 
450
 
 
451
                if (gtk_recent_info_has_group (info, "Totem")) {
 
452
                        gtk_recent_info_ref (info);
 
453
                        totem_items = g_list_prepend (totem_items, info);
 
454
                }
 
455
        }
 
456
        g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
 
457
        g_list_free (items);
 
458
 
 
459
        totem_items = g_list_sort (totem_items, (GCompareFunc) totem_compare_recent_items);
 
460
 
 
461
        for (l = totem_items; l && l->data; l = l->next) {
 
462
                GtkRecentInfo *info;
 
463
                GtkAction     *action;
 
464
                char           action_name[32];
 
465
                const char    *display_name;
 
466
                char          *label;
 
467
                char          *escaped_label;
 
468
                const gchar   *mime_type;
 
469
                gchar         *content_type;
 
470
                GIcon         *icon = NULL;
 
471
 
 
472
                info = (GtkRecentInfo *) l->data;
 
473
 
 
474
                if (!gtk_recent_info_has_group (info, "Totem"))
 
475
                        continue;
 
476
 
 
477
                g_snprintf (action_name, sizeof (action_name), "RecentFile%u", n_items);
 
478
 
 
479
                display_name = gtk_recent_info_get_display_name (info);
 
480
                escaped_label = escape_label_for_menu (display_name);
 
481
 
 
482
                label = g_strdup_printf ("_%d.  %s", n_items + 1, escaped_label);
 
483
                g_free (escaped_label);
 
484
 
 
485
                action = gtk_action_new (action_name, label, NULL, NULL);
 
486
                g_object_set_data_full (G_OBJECT (action), "recent-info",
 
487
                                        gtk_recent_info_ref (info),
 
488
                                        (GDestroyNotify) gtk_recent_info_unref);
 
489
                g_signal_connect (G_OBJECT (action), "activate",
 
490
                                  G_CALLBACK (on_recent_file_item_activated),
 
491
                                  totem);
 
492
 
 
493
                mime_type = gtk_recent_info_get_mime_type (info);
 
494
                content_type = g_content_type_from_mime_type (mime_type);
 
495
                if (content_type != NULL) {
 
496
                        icon = g_content_type_get_icon (content_type);
 
497
                        g_free (content_type);
 
498
                }
 
499
                if (icon != NULL) {
 
500
                        gtk_action_set_gicon (action, icon);
 
501
                        gtk_action_set_always_show_image (action, TRUE);
 
502
                        g_object_unref (icon);
 
503
                }
 
504
 
 
505
                gtk_action_group_add_action (totem->recent_action_group,
 
506
                                            action);
 
507
                g_object_unref (action);
 
508
 
 
509
                gtk_ui_manager_add_ui (totem->ui_manager, totem->recent_ui_id,
 
510
                                      "/tmw-menubar/movie/recent-placeholder",
 
511
                                      label, action_name, GTK_UI_MANAGER_MENUITEM,
 
512
                                      FALSE);
 
513
                g_free (label);
 
514
 
 
515
                if (++n_items == 5)
 
516
                        break;
 
517
        }
 
518
 
 
519
        g_list_foreach (totem_items, (GFunc) gtk_recent_info_unref, NULL);
 
520
        g_list_free (totem_items);
 
521
}
 
522
 
 
523
void
 
524
totem_setup_recent (Totem *totem)
 
525
{
 
526
        totem->recent_manager = gtk_recent_manager_get_default ();
 
527
        totem->recent_action_group = NULL;
 
528
        totem->recent_ui_id = 0;
 
529
 
 
530
        g_signal_connect (G_OBJECT (totem->recent_manager), "changed",
 
531
                        G_CALLBACK (totem_recent_manager_changed_callback),
 
532
                        totem);
 
533
 
 
534
        totem_recent_manager_changed_callback (totem->recent_manager, totem);
 
535
}
 
536
 
 
537
static void
 
538
recent_info_cb (GFile *file,
 
539
                GAsyncResult *res,
 
540
                Totem *totem)
 
541
{
 
542
        GtkRecentData data;
 
543
        char *groups[] = { NULL, NULL };
 
544
        GFileInfo *file_info;
 
545
        const char *uri, *display_name;
 
546
 
 
547
        memset (&data, 0, sizeof (data));
 
548
 
 
549
        file_info = g_file_query_info_finish (file, res, NULL);
 
550
        uri = g_object_get_data (G_OBJECT (file), "uri");
 
551
        display_name = g_object_get_data (G_OBJECT (file), "display_name");
 
552
 
 
553
        /* Probably an unsupported URI scheme */
 
554
        if (file_info == NULL) {
 
555
                data.display_name = g_strdup (display_name);
 
556
                /* Bogus mime-type, we just want it added */
 
557
                data.mime_type = g_strdup ("video/x-totem-stream");
 
558
                groups[0] = (gchar*) "TotemStreams";
 
559
        } else {
 
560
                data.mime_type = g_strdup (g_file_info_get_content_type (file_info));
 
561
                data.display_name = g_strdup (g_file_info_get_display_name (file_info));
 
562
                g_object_unref (file_info);
 
563
                groups[0] = (gchar*) "Totem";
 
564
        }
 
565
 
 
566
        data.app_name = g_strdup (g_get_application_name ());
 
567
        data.app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
 
568
        data.groups = groups;
 
569
        if (gtk_recent_manager_add_full (totem->recent_manager,
 
570
                                         uri, &data) == FALSE) {
 
571
                g_warning ("Couldn't add recent file for '%s'", uri);
 
572
        }
 
573
 
 
574
        g_free (data.display_name);
 
575
        g_free (data.mime_type);
 
576
        g_free (data.app_name);
 
577
        g_free (data.app_exec);
 
578
 
 
579
        g_object_unref (file);
 
580
}
 
581
 
 
582
void
 
583
totem_action_add_recent (Totem      *totem,
 
584
                         const char *uri,
 
585
                         const char *display_name,
 
586
                         const char *content_type)
 
587
{
 
588
        GFile *file;
 
589
 
 
590
        if (totem_is_special_mrl (uri) != FALSE)
 
591
                return;
 
592
 
 
593
        /* If we already have a content-type, the display_name is
 
594
         * probably decent as well */
 
595
        if (content_type != NULL) {
 
596
                GtkRecentData data;
 
597
                char *groups[] = { NULL, NULL };
 
598
 
 
599
                memset (&data, 0, sizeof (data));
 
600
 
 
601
                data.mime_type = (char *) content_type;
 
602
                data.display_name = (char *) display_name;
 
603
                groups[0] = (char*) "Totem";
 
604
                data.app_name = (char *) g_get_application_name ();
 
605
                data.app_exec = g_strjoin (" ", g_get_prgname (), "%u", NULL);
 
606
                data.groups = groups;
 
607
 
 
608
                if (gtk_recent_manager_add_full (totem->recent_manager,
 
609
                                                 uri, &data) == FALSE) {
 
610
                        g_warning ("Couldn't add recent file for '%s'", uri);
 
611
                }
 
612
                g_free (data.app_exec);
 
613
 
 
614
                return;
 
615
        }
 
616
 
 
617
        file = g_file_new_for_uri (uri);
 
618
        g_object_set_data_full (G_OBJECT (file), "uri", g_strdup (uri), g_free);
 
619
        g_object_set_data_full (G_OBJECT (file), "display_name", g_strdup (display_name), g_free);
 
620
        g_file_query_info_async (file,
 
621
                                 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
 
622
                                 G_FILE_QUERY_INFO_NONE, 0, NULL, (GAsyncReadyCallback) recent_info_cb, totem);
 
623
}
 
624
 
 
625
/* Play Disc menu items */
 
626
 
 
627
static void
 
628
on_play_disc_activate (GtkAction *action, Totem *totem)
 
629
{
 
630
        char *device_path;
 
631
 
 
632
        device_path = g_object_get_data (G_OBJECT (action), "device_path");
 
633
        totem_action_play_media_device (totem, device_path);
 
634
}
 
635
 
 
636
static const char *
 
637
get_icon_name_for_gicon (GtkIconTheme *theme,
 
638
                         GIcon *icon)
 
639
{
 
640
        const char * const *icon_names;
 
641
        const char *icon_name;
 
642
        guint j;
 
643
 
 
644
        icon_name = NULL;
 
645
 
 
646
        if (G_IS_EMBLEMED_ICON (icon) != FALSE) {
 
647
                GIcon *new_icon;
 
648
                new_icon = g_emblemed_icon_get_icon (G_EMBLEMED_ICON (icon));
 
649
                g_object_unref (icon);
 
650
                icon = g_object_ref (new_icon);
 
651
        }
 
652
 
 
653
        if (G_IS_THEMED_ICON (icon)) {
 
654
                icon_names = g_themed_icon_get_names (G_THEMED_ICON (icon));
 
655
 
 
656
                for (j = 0; icon_names[j] != NULL; j++) {
 
657
                        icon_name = icon_names[j];
 
658
                        if (gtk_icon_theme_has_icon (theme, icon_name) != FALSE)
 
659
                                break;
 
660
                }
 
661
        }
 
662
 
 
663
        return icon_name;
 
664
}
 
665
 
 
666
static char *
 
667
unescape_archive_name (GFile *root)
 
668
{
 
669
        char *uri;
 
670
        guint len;
 
671
        char *escape1, *escape2;
 
672
 
 
673
        uri = g_file_get_uri (root);
 
674
 
 
675
        /* Remove trailing slash */
 
676
        len = strlen (uri);
 
677
        if (uri[len - 1] == '/')
 
678
                uri[len - 1] = '\0';
 
679
 
 
680
        /* Unescape the path */
 
681
        escape1 = g_uri_unescape_string (uri + strlen ("archive://"), NULL);
 
682
        escape2 = g_uri_unescape_string (escape1, NULL);
 
683
        g_free (escape1);
 
684
        g_free (uri);
 
685
 
 
686
        return escape2;
 
687
}
 
688
 
 
689
static void
 
690
add_mount_to_menu (GMount *mount,
 
691
                   GtkIconTheme *theme,
 
692
                   guint position,
 
693
                   Totem *totem)
 
694
{
 
695
        char *name, *escaped_name, *label;
 
696
        GtkAction *action;
 
697
        GIcon *icon;
 
698
        const char *icon_name;
 
699
        char *device_path;
 
700
 
 
701
        GVolume *volume;
 
702
        GFile *root, *iso;
 
703
        char **content_types;
 
704
        gboolean has_content;
 
705
        guint i;
 
706
 
 
707
        /* Check whether we have an archive mount */
 
708
        volume = g_mount_get_volume (mount);
 
709
        if (volume != NULL) {
 
710
                g_object_unref (volume);
 
711
                return;
 
712
        }
 
713
 
 
714
        root = g_mount_get_root (mount);
 
715
        if (g_file_has_uri_scheme (root, "archive") == FALSE) {
 
716
                g_object_unref (root);
 
717
                return;
 
718
        }
 
719
 
 
720
        /* Check whether it's a DVD or VCD image */
 
721
        content_types = g_content_type_guess_for_tree (root);
 
722
        if (content_types == NULL ||
 
723
            g_strv_length (content_types) == 0) {
 
724
                g_strfreev (content_types);
 
725
                g_object_unref (root);
 
726
                return;
 
727
        }
 
728
 
 
729
        has_content = FALSE;
 
730
        for (i = 0; content_types[i] != NULL; i++) {
 
731
                /* XXX: Keep in sync with mime-type-list.txt */
 
732
                if (g_str_equal (content_types[i], "x-content/video-dvd") ||
 
733
                    g_str_equal (content_types[i], "x-content/video-vcd") ||
 
734
                    g_str_equal (content_types[i], "x-content/video-svcd")) {
 
735
                        has_content = TRUE;
 
736
                        break;
 
737
                }
 
738
        }
 
739
        g_strfreev (content_types);
 
740
 
 
741
        if (has_content == FALSE) {
 
742
                g_object_unref (root);
 
743
                return;
 
744
        }
 
745
 
 
746
        device_path = unescape_archive_name (root);
 
747
        g_object_unref (root);
 
748
 
 
749
        /* And ensure it's a local path */
 
750
        iso = g_file_new_for_uri (device_path);
 
751
        g_free (device_path);
 
752
        device_path = g_file_get_path (iso);
 
753
        g_object_unref (iso);
 
754
 
 
755
        /* Work out an icon to display */
 
756
        icon = g_mount_get_icon (mount);
 
757
        icon_name = get_icon_name_for_gicon (theme, icon);
 
758
 
 
759
        /* Get the mount's pretty name for the menu label */
 
760
        name = g_mount_get_name (mount);
 
761
        g_strstrip (name);
 
762
        escaped_name = escape_label_for_menu (name);
 
763
        g_free (name);
 
764
        /* Translators:
 
765
         * This is not a JPEG image, but a disc image, for example,
 
766
         * an ISO file */
 
767
        label = g_strdup_printf (_("Play Image '%s'"), escaped_name);
 
768
        g_free (escaped_name);
 
769
 
 
770
        name = g_strdup_printf (_("device%d"), position);
 
771
 
 
772
        action = gtk_action_new (name, label, NULL, NULL);
 
773
        g_object_set (G_OBJECT (action),
 
774
                      "icon-name", icon_name, NULL);
 
775
        gtk_action_set_always_show_image (action, TRUE);
 
776
        gtk_action_group_add_action (totem->devices_action_group, action);
 
777
        g_object_unref (action);
 
778
 
 
779
        gtk_ui_manager_add_ui (totem->ui_manager, totem->devices_ui_id,
 
780
                               "/tmw-menubar/movie/devices-placeholder", name, name,
 
781
                               GTK_UI_MANAGER_MENUITEM, FALSE);
 
782
 
 
783
        g_free (name);
 
784
        g_free (label);
 
785
        g_object_unref (icon);
 
786
 
 
787
        g_object_set_data_full (G_OBJECT (action),
 
788
                                "device_path", device_path,
 
789
                                (GDestroyNotify) g_free);
 
790
 
 
791
        g_signal_connect (G_OBJECT (action), "activate",
 
792
                          G_CALLBACK (on_play_disc_activate), totem);
 
793
}
 
794
 
 
795
static void
 
796
add_volume_to_menu (GVolume *volume,
 
797
                    GDrive *drive,
 
798
                    GtkIconTheme *theme,
 
799
                    guint position,
 
800
                    Totem *totem)
 
801
{
 
802
        char *name, *escaped_name, *label;
 
803
        GtkAction *action;
 
804
        gboolean disabled;
 
805
        GIcon *icon;
 
806
        const char *icon_name;
 
807
        char *device_path;
 
808
        GtkWidget *menu_item;
 
809
        char *menu_item_path;
 
810
 
 
811
        disabled = FALSE;
 
812
        device_path = NULL;
 
813
 
 
814
        /* Add devices with blank CDs and audio CDs in them, but disable them */
 
815
        if (drive != NULL) {
 
816
                device_path = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
 
817
                if (device_path == NULL)
 
818
                        return;
 
819
        }
 
820
 
 
821
        /* Check whether we have a media... */
 
822
        if (drive != NULL &&
 
823
            g_drive_has_media (drive) == FALSE) {
 
824
                disabled = TRUE;
 
825
        } else {
 
826
                /* ... Or an audio CD or a blank media */
 
827
                GMount *mount;
 
828
                GFile *root;
 
829
 
 
830
                mount = g_volume_get_mount (volume);
 
831
                if (mount != NULL) {
 
832
                        root = g_mount_get_root (mount);
 
833
                        g_object_unref (mount);
 
834
 
 
835
                        if (g_file_has_uri_scheme (root, "burn") != FALSE || g_file_has_uri_scheme (root, "cdda") != FALSE)
 
836
                                disabled = TRUE;
 
837
                        g_object_unref (root);
 
838
                }
 
839
        }
 
840
 
 
841
        /* Work out an icon to display */
 
842
        icon = g_volume_get_icon (volume);
 
843
        icon_name = get_icon_name_for_gicon (theme, icon);
 
844
 
 
845
        /* Get the volume's pretty name for the menu label */
 
846
        name = g_volume_get_name (volume);
 
847
        g_strstrip (name);
 
848
        escaped_name = escape_label_for_menu (name);
 
849
        g_free (name);
 
850
        label = g_strdup_printf (_("Play Disc '%s'"), escaped_name);
 
851
        g_free (escaped_name);
 
852
 
 
853
        name = g_strdup_printf (_("device%d"), position);
 
854
 
 
855
        action = gtk_action_new (name, label, NULL, NULL);
 
856
        g_object_set (G_OBJECT (action),
 
857
                      "icon-name", icon_name,
 
858
                      "sensitive", !disabled, NULL);
 
859
        gtk_action_group_add_action (totem->devices_action_group, action);
 
860
        g_object_unref (action);
 
861
 
 
862
        gtk_ui_manager_add_ui (totem->ui_manager, totem->devices_ui_id,
 
863
                               "/tmw-menubar/movie/devices-placeholder", name, name,
 
864
                               GTK_UI_MANAGER_MENUITEM, FALSE);
 
865
 
 
866
        /* TODO: This can be made cleaner once bug #589842 is fixed */
 
867
        menu_item_path = g_strdup_printf ("/tmw-menubar/movie/devices-placeholder/%s", name);
 
868
        menu_item = gtk_ui_manager_get_widget (totem->ui_manager, menu_item_path);
 
869
        g_free (menu_item_path);
 
870
 
 
871
        if (menu_item != NULL)
 
872
                gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (menu_item), TRUE);
 
873
 
 
874
        g_free (name);
 
875
        g_free (label);
 
876
        g_object_unref (icon);
 
877
 
 
878
        if (disabled != FALSE) {
 
879
                g_free (device_path);
 
880
                return;
 
881
        }
 
882
 
 
883
        g_object_set_data_full (G_OBJECT (action),
 
884
                                "device_path", device_path,
 
885
                                (GDestroyNotify) g_free);
 
886
 
 
887
        g_signal_connect (G_OBJECT (action), "activate",
 
888
                          G_CALLBACK (on_play_disc_activate), totem);
 
889
}
 
890
 
 
891
static void
 
892
add_drive_to_menu (GDrive *drive,
 
893
                   GtkIconTheme *theme,
 
894
                   guint position,
 
895
                   Totem *totem)
 
896
{
 
897
        GList *volumes, *i;
 
898
 
 
899
        /* FIXME: We used to explicitly check whether it was a CD/DVD drive
 
900
         * Use:
 
901
         * udi = g_volume_get_identifier (i->data, G_VOLUME_IDENTIFIER_KIND_HAL_UDI); */
 
902
        if (g_drive_can_eject (drive) == FALSE)
 
903
                return;
 
904
 
 
905
        /* Repeat for all the drive's volumes */
 
906
        volumes = g_drive_get_volumes (drive);
 
907
 
 
908
        for (i = volumes; i != NULL; i = i->next) {
 
909
                GVolume *volume = i->data;
 
910
                add_volume_to_menu (volume, drive, theme, position, totem);
 
911
                g_object_unref (volume);
 
912
        }
 
913
 
 
914
        g_list_free (volumes);
 
915
}
 
916
 
 
917
static void
 
918
update_drive_menu_items (GtkMenuItem *movie_menuitem, Totem *totem)
 
919
{
 
920
        GList *drives, *mounts, *i;
 
921
        GtkIconTheme *theme;
 
922
        guint position;
 
923
 
 
924
        /* Add any suitable devices to the menu */
 
925
        position = 0;
 
926
 
 
927
        theme = gtk_icon_theme_get_default ();
 
928
 
 
929
        drives = g_volume_monitor_get_connected_drives (totem->monitor);
 
930
        for (i = drives; i != NULL; i = i->next) {
 
931
                GDrive *drive = i->data;
 
932
 
 
933
                position++;
 
934
                add_drive_to_menu (drive, theme, position, totem);
 
935
                g_object_unref (drive);
 
936
        }
 
937
        g_list_free (drives);
 
938
 
 
939
        /* Look for mounted archives */
 
940
        mounts = g_volume_monitor_get_mounts (totem->monitor);
 
941
        for (i = mounts; i != NULL; i = i->next) {
 
942
                GMount *mount = i->data;
 
943
 
 
944
                position++;
 
945
                add_mount_to_menu (mount, theme, position, totem);
 
946
                g_object_unref (mount);
 
947
        }
 
948
        g_list_free (mounts);
 
949
 
 
950
        totem->drives_changed = FALSE;
 
951
}
 
952
 
 
953
static void
 
954
on_movie_menu_select (GtkMenuItem *movie_menuitem, Totem *totem)
 
955
{
 
956
        if (totem->drives_changed == FALSE)
 
957
                return;
 
958
 
 
959
        /* Remove old UI */
 
960
        gtk_ui_manager_remove_ui (totem->ui_manager, totem->devices_ui_id);
 
961
        gtk_ui_manager_ensure_update (totem->ui_manager);
 
962
 
 
963
        /* Create new ActionGroup */
 
964
        if (totem->devices_action_group) {
 
965
                gtk_ui_manager_remove_action_group (totem->ui_manager,
 
966
                                totem->devices_action_group);
 
967
                g_object_unref (totem->devices_action_group);
 
968
        }
 
969
        totem->devices_action_group = gtk_action_group_new ("devices-action-group");
 
970
        gtk_ui_manager_insert_action_group (totem->ui_manager,
 
971
                        totem->devices_action_group, -1);
 
972
 
 
973
        update_drive_menu_items (movie_menuitem, totem);
 
974
 
 
975
        gtk_ui_manager_ensure_update (totem->ui_manager);
 
976
}
 
977
 
 
978
static void
 
979
on_g_volume_monitor_event (GVolumeMonitor *monitor,
 
980
                           gpointer *device,
 
981
                           Totem *totem)
 
982
{
 
983
        totem->drives_changed = TRUE;
 
984
}
 
985
 
 
986
void
 
987
totem_setup_play_disc (Totem *totem)
 
988
{
 
989
        GtkWidget *item;
 
990
 
 
991
        item = gtk_ui_manager_get_widget (totem->ui_manager, "/tmw-menubar/movie");
 
992
        g_signal_connect (G_OBJECT (item), "select",
 
993
                        G_CALLBACK (on_movie_menu_select), totem);
 
994
 
 
995
        g_signal_connect (G_OBJECT (totem->monitor),
 
996
                        "volume-added",
 
997
                        G_CALLBACK (on_g_volume_monitor_event), totem);
 
998
        g_signal_connect (G_OBJECT (totem->monitor),
 
999
                        "volume-removed",
 
1000
                        G_CALLBACK (on_g_volume_monitor_event), totem);
 
1001
        g_signal_connect (G_OBJECT (totem->monitor),
 
1002
                        "mount-added",
 
1003
                        G_CALLBACK (on_g_volume_monitor_event), totem);
 
1004
        g_signal_connect (G_OBJECT (totem->monitor),
 
1005
                        "mount-removed",
 
1006
                        G_CALLBACK (on_g_volume_monitor_event), totem);
 
1007
 
 
1008
        totem->drives_changed = TRUE;
 
1009
}
 
1010
 
 
1011
void
 
1012
open_action_callback (GtkAction *action, Totem *totem)
 
1013
{
 
1014
        totem_action_open (totem);
 
1015
}
 
1016
 
 
1017
void
 
1018
open_location_action_callback (GtkAction *action, Totem *totem)
 
1019
{
 
1020
        totem_action_open_location (totem);
 
1021
}
 
1022
 
 
1023
void
 
1024
eject_action_callback (GtkAction *action, Totem *totem)
 
1025
{
 
1026
        totem_action_eject (totem);
 
1027
}
 
1028
 
 
1029
void
 
1030
properties_action_callback (GtkAction *action, Totem *totem)
 
1031
{
 
1032
        totem_action_show_properties (totem);
 
1033
}
 
1034
 
 
1035
void
 
1036
play_action_callback (GtkAction *action, Totem *totem)
 
1037
{
 
1038
        totem_action_play_pause (totem);
 
1039
}
 
1040
 
 
1041
G_GNUC_NORETURN void
 
1042
quit_action_callback (GtkAction *action, Totem *totem)
 
1043
{
 
1044
        totem_action_exit (totem);
 
1045
}
 
1046
 
 
1047
void
 
1048
preferences_action_callback (GtkAction *action, Totem *totem)
 
1049
{
 
1050
        gtk_widget_show (totem->prefs);
 
1051
}
 
1052
 
 
1053
void
 
1054
fullscreen_action_callback (GtkAction *action, Totem *totem)
 
1055
{
 
1056
        totem_action_fullscreen_toggle (totem);
 
1057
}
 
1058
 
 
1059
void
 
1060
zoom_1_2_action_callback (GtkAction *action, Totem *totem)
 
1061
{
 
1062
        totem_action_set_scale_ratio (totem, 0.5); 
 
1063
}
 
1064
 
 
1065
void
 
1066
zoom_1_1_action_callback (GtkAction *action, Totem *totem)
 
1067
{
 
1068
        totem_action_set_scale_ratio (totem, 1);
 
1069
}
 
1070
 
 
1071
void
 
1072
zoom_2_1_action_callback (GtkAction *action, Totem *totem)
 
1073
{
 
1074
        totem_action_set_scale_ratio (totem, 2);
 
1075
}
 
1076
 
 
1077
void
 
1078
zoom_in_action_callback (GtkAction *action, Totem *totem)
 
1079
{
 
1080
        totem_action_zoom_relative (totem, ZOOM_IN_OFFSET);
 
1081
}
 
1082
 
 
1083
void
 
1084
zoom_reset_action_callback (GtkAction *action, Totem *totem)
 
1085
{
 
1086
        totem_action_zoom_reset (totem);
 
1087
}
 
1088
 
 
1089
void
 
1090
zoom_out_action_callback (GtkAction *action, Totem *totem)
 
1091
{
 
1092
        totem_action_zoom_relative (totem, ZOOM_OUT_OFFSET);
 
1093
}
 
1094
 
 
1095
void
 
1096
select_subtitle_action_callback (GtkAction *action, Totem *totem)
 
1097
{
 
1098
        totem_playlist_select_subtitle_dialog (totem->playlist,
 
1099
                                               TOTEM_PLAYLIST_DIALOG_PLAYING);
 
1100
 
1101
 
 
1102
void
 
1103
next_angle_action_callback (GtkAction *action, Totem *totem)
 
1104
{
 
1105
        totem_action_next_angle (totem);
 
1106
}
 
1107
 
 
1108
void
 
1109
dvd_root_menu_action_callback (GtkAction *action, Totem *totem)
 
1110
{
 
1111
        bacon_video_widget_dvd_event (totem->bvw, BVW_DVD_ROOT_MENU);
 
1112
}
 
1113
 
 
1114
void
 
1115
dvd_title_menu_action_callback (GtkAction *action, Totem *totem)
 
1116
{
 
1117
        bacon_video_widget_dvd_event (totem->bvw, BVW_DVD_TITLE_MENU);
 
1118
}
 
1119
 
 
1120
void
 
1121
dvd_audio_menu_action_callback (GtkAction *action, Totem *totem)
 
1122
{
 
1123
        bacon_video_widget_dvd_event (totem->bvw, BVW_DVD_AUDIO_MENU);
 
1124
}
 
1125
 
 
1126
void
 
1127
dvd_angle_menu_action_callback (GtkAction *action, Totem *totem)
 
1128
{
 
1129
        bacon_video_widget_dvd_event (totem->bvw, BVW_DVD_ANGLE_MENU);
 
1130
}
 
1131
 
 
1132
void
 
1133
dvd_chapter_menu_action_callback (GtkAction *action, Totem *totem)
 
1134
{
 
1135
        bacon_video_widget_dvd_event (totem->bvw, BVW_DVD_CHAPTER_MENU);
 
1136
}
 
1137
 
 
1138
void
 
1139
next_chapter_action_callback (GtkAction *action, Totem *totem)
 
1140
{
 
1141
        TOTEM_PROFILE (totem_action_next (totem));
 
1142
}
 
1143
 
 
1144
void
 
1145
previous_chapter_action_callback (GtkAction *action, Totem *totem)
 
1146
{
 
1147
        TOTEM_PROFILE (totem_action_previous (totem));
 
1148
}
 
1149
 
 
1150
void
 
1151
skip_forward_action_callback (GtkAction *action, Totem *totem)
 
1152
{
 
1153
        totem_action_seek_relative (totem, SEEK_FORWARD_OFFSET * 1000, FALSE);
 
1154
}
 
1155
 
 
1156
void
 
1157
skip_backwards_action_callback (GtkAction *action, Totem *totem)
 
1158
{
 
1159
        totem_action_seek_relative (totem, SEEK_BACKWARD_OFFSET * 1000, FALSE);
 
1160
}
 
1161
 
 
1162
void
 
1163
volume_up_action_callback (GtkAction *action, Totem *totem)
 
1164
{
 
1165
        totem_action_volume_relative (totem, VOLUME_UP_OFFSET);
 
1166
}
 
1167
 
 
1168
void
 
1169
volume_down_action_callback (GtkAction *action, Totem *totem)
 
1170
{
 
1171
        totem_action_volume_relative (totem, VOLUME_DOWN_OFFSET);
 
1172
}
 
1173
 
 
1174
void
 
1175
contents_action_callback (GtkAction *action, Totem *totem)
 
1176
{
 
1177
        totem_action_show_help (totem);
 
1178
}
 
1179
 
 
1180
void
 
1181
about_action_callback (GtkAction *action, Totem *totem)
 
1182
{
 
1183
        char *backend_version, *description;
 
1184
 
 
1185
        const char *authors[] =
 
1186
        {
 
1187
                "Bastien Nocera <hadess@hadess.net>",
 
1188
                "Ronald Bultje <rbultje@ronald.bitfreak.net>",
 
1189
                "Julien Moutte <julien@moutte.net> (GStreamer backend)",
 
1190
                "Tim-Philipp M\303\274ller <tim\100centricular\056net> (GStreamer backend)",
 
1191
                "Philip Withnall <philip@tecnocode.co.uk>",
 
1192
                NULL
 
1193
        };
 
1194
        const char *artists[] = { "Jakub Steiner <jimmac@ximian.com>", NULL };
 
1195
        #include "../help/totem-docs.h"
 
1196
        char *license = totem_interface_get_license ();
 
1197
 
 
1198
        backend_version = bacon_video_widget_get_backend_name (totem->bvw);
 
1199
        /* This lists the back-end type and version, such as
 
1200
         * Movie Player using GStreamer 0.10.1 */
 
1201
        description = g_strdup_printf (_("Movie Player using %s"), backend_version);
 
1202
 
 
1203
        gtk_show_about_dialog (GTK_WINDOW (totem->win),
 
1204
                                     "version", VERSION,
 
1205
                                     "copyright", _("Copyright \xc2\xa9 2002-2009 Bastien Nocera"),
 
1206
                                     "comments", description,
 
1207
                                     "authors", authors,
 
1208
                                     "documenters", documentation_credits,
 
1209
                                     "artists", artists,
 
1210
                                     "translator-credits", _("translator-credits"),
 
1211
                                     "logo-icon-name", "totem",
 
1212
                                     "license", license,
 
1213
                                     "wrap-license", TRUE,
 
1214
                                     "website-label", _("Totem Website"),
 
1215
                                     "website", "http://projects.gnome.org/totem/",
 
1216
                                     NULL);
 
1217
 
 
1218
        g_free (backend_version);
 
1219
        g_free (description);
 
1220
        g_free (license);
 
1221
}
 
1222
 
 
1223
static gboolean
 
1224
totem_plugins_window_delete_cb (GtkWidget *window,
 
1225
                                   GdkEventAny *event,
 
1226
                                   gpointer data)
 
1227
{
 
1228
        gtk_widget_hide (window);
 
1229
 
 
1230
        return TRUE;
 
1231
}
 
1232
 
 
1233
static void
 
1234
totem_plugins_response_cb (GtkDialog *dialog,
 
1235
                              int response_id,
 
1236
                              gpointer data)
 
1237
{
 
1238
        gtk_widget_hide (GTK_WIDGET (dialog));
 
1239
}
 
1240
 
 
1241
 
 
1242
void
 
1243
plugins_action_callback (GtkAction *action, Totem *totem)
 
1244
{
 
1245
        if (totem->plugins == NULL) {
 
1246
                GtkWidget *manager;
 
1247
 
 
1248
                totem->plugins = gtk_dialog_new_with_buttons (_("Configure Plugins"),
 
1249
                                                              GTK_WINDOW (totem->win),
 
1250
                                                              GTK_DIALOG_DESTROY_WITH_PARENT,
 
1251
                                                              GTK_STOCK_CLOSE,
 
1252
                                                              GTK_RESPONSE_CLOSE,
 
1253
                                                              NULL);
 
1254
                gtk_container_set_border_width (GTK_CONTAINER (totem->plugins), 5);
 
1255
                gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (totem->plugins))), 2);
 
1256
 
 
1257
                g_signal_connect_object (G_OBJECT (totem->plugins),
 
1258
                                         "delete_event",
 
1259
                                         G_CALLBACK (totem_plugins_window_delete_cb),
 
1260
                                         NULL, 0);
 
1261
                g_signal_connect_object (G_OBJECT (totem->plugins),
 
1262
                                         "response",
 
1263
                                         G_CALLBACK (totem_plugins_response_cb),
 
1264
                                         NULL, 0);
 
1265
 
 
1266
                manager = peas_gtk_plugin_manager_new (NULL);
 
1267
                gtk_widget_show_all (GTK_WIDGET (manager));
 
1268
                gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (totem->plugins))),
 
1269
                                    manager, TRUE, TRUE, 0);
 
1270
                gtk_window_set_default_size (GTK_WINDOW (totem->plugins), 600, 400);
 
1271
        }
 
1272
 
 
1273
        gtk_window_present (GTK_WINDOW (totem->plugins));
 
1274
}
 
1275
 
 
1276
void
 
1277
repeat_mode_action_callback (GtkToggleAction *action, Totem *totem)
 
1278
{
 
1279
        totem_playlist_set_repeat (totem->playlist,
 
1280
                        gtk_toggle_action_get_active (action));
 
1281
}
 
1282
 
 
1283
void
 
1284
shuffle_mode_action_callback (GtkToggleAction *action, Totem *totem)
 
1285
{
 
1286
        totem_playlist_set_shuffle (totem->playlist,
 
1287
                        gtk_toggle_action_get_active (action));
 
1288
}
 
1289
 
 
1290
void
 
1291
show_controls_action_callback (GtkToggleAction *action, Totem *totem)
 
1292
{
 
1293
        gboolean show;
 
1294
 
 
1295
        show = gtk_toggle_action_get_active (action);
 
1296
 
 
1297
        /* Let's update our controls visibility */
 
1298
        if (show)
 
1299
                totem->controls_visibility = TOTEM_CONTROLS_VISIBLE;
 
1300
        else
 
1301
                totem->controls_visibility = TOTEM_CONTROLS_HIDDEN;
 
1302
 
 
1303
        show_controls (totem, FALSE);
 
1304
}
 
1305
 
 
1306
void
 
1307
show_sidebar_action_callback (GtkToggleAction *action, Totem *totem)
 
1308
{
 
1309
        if (totem_is_fullscreen (totem))
 
1310
                return;
 
1311
 
 
1312
        totem_sidebar_toggle (totem, gtk_toggle_action_get_active (action));
 
1313
}
 
1314
 
 
1315
void
 
1316
aspect_ratio_changed_callback (GtkRadioAction *action, GtkRadioAction *current, Totem *totem)
 
1317
{
 
1318
        totem_action_set_aspect_ratio (totem, gtk_radio_action_get_current_value (current));
 
1319
}
 
1320
 
 
1321
void
 
1322
clear_playlist_action_callback (GtkAction *action, Totem *totem)
 
1323
{
 
1324
        totem_playlist_clear (totem->playlist);
 
1325
        totem_action_set_mrl (totem, NULL, NULL);
 
1326
}
 
1327
 
 
1328
/* Show help in status bar when selecting (hovering over) a menu item. */
 
1329
static void
 
1330
menu_item_select_cb (GtkMenuItem *proxy, Totem *totem)
 
1331
{
 
1332
        GtkAction *action;
 
1333
        const gchar *message;
 
1334
 
 
1335
        action = gtk_activatable_get_related_action (GTK_ACTIVATABLE (proxy));
 
1336
        g_return_if_fail (action != NULL);
 
1337
 
 
1338
        message = gtk_action_get_tooltip (action);
 
1339
        if (message)
 
1340
                totem_statusbar_push_help (TOTEM_STATUSBAR (totem->statusbar), message);
 
1341
}
 
1342
 
 
1343
static void
 
1344
menu_item_deselect_cb (GtkMenuItem *proxy, Totem *totem)
 
1345
{
 
1346
        totem_statusbar_pop_help (TOTEM_STATUSBAR (totem->statusbar));
 
1347
}
 
1348
 
 
1349
static void
 
1350
setup_action (Totem *totem, GtkAction *action)
 
1351
{
 
1352
        GSList *proxies;
 
1353
        for (proxies = gtk_action_get_proxies (action); proxies != NULL; proxies = proxies->next) {
 
1354
                if (GTK_IS_MENU_ITEM (proxies->data)) {
 
1355
                        g_signal_connect (proxies->data, "select", G_CALLBACK (menu_item_select_cb), totem);
 
1356
                        g_signal_connect (proxies->data, "deselect", G_CALLBACK (menu_item_deselect_cb), totem);
 
1357
                }
 
1358
 
 
1359
        }
 
1360
}
 
1361
 
 
1362
static void
 
1363
setup_menu_items (Totem *totem)
 
1364
{
 
1365
        GList *action_groups;
 
1366
 
 
1367
        /* FIXME: We can remove this once GTK+ bug #574001 is fixed */
 
1368
        for (action_groups = gtk_ui_manager_get_action_groups (totem->ui_manager);
 
1369
             action_groups != NULL; action_groups = action_groups->next) {
 
1370
                GtkActionGroup *action_group = GTK_ACTION_GROUP (action_groups->data);
 
1371
                GList *actions;
 
1372
                for (actions = gtk_action_group_list_actions (action_group); actions != NULL; actions = actions->next) {
 
1373
                        setup_action (totem, GTK_ACTION (actions->data));
 
1374
                }
 
1375
        }
 
1376
}
 
1377
 
 
1378
void
 
1379
totem_ui_manager_setup (Totem *totem)
 
1380
{
 
1381
        totem->main_action_group = GTK_ACTION_GROUP (gtk_builder_get_object (totem->xml, "main-action-group"));
 
1382
        totem->zoom_action_group = GTK_ACTION_GROUP (gtk_builder_get_object (totem->xml, "zoom-action-group"));
 
1383
 
 
1384
        /* FIXME: Moving these to GtkBuilder depends on bug #457631 */
 
1385
        if (gtk_widget_get_direction (totem->win) == GTK_TEXT_DIR_RTL) {
 
1386
                GtkActionGroup *action_group = GTK_ACTION_GROUP (gtk_builder_get_object (totem->xml, "skip-action-group"));
 
1387
                GtkAction *action;
 
1388
 
 
1389
                action = gtk_action_group_get_action (action_group, "skip-forward");
 
1390
                gtk_action_set_accel_path (action, "Left");
 
1391
 
 
1392
                action = gtk_action_group_get_action (action_group, "skip-backwards");
 
1393
                gtk_action_set_accel_path (action, "Right");
 
1394
        }
 
1395
 
 
1396
        totem->ui_manager = GTK_UI_MANAGER (gtk_builder_get_object (totem->xml, "totem-ui-manager"));
 
1397
 
 
1398
        setup_menu_items (totem);
 
1399
 
 
1400
        totem->devices_action_group = NULL;
 
1401
        totem->devices_ui_id = gtk_ui_manager_new_merge_id (totem->ui_manager);
 
1402
        totem->languages_action_group = NULL;
 
1403
        totem->languages_ui_id = gtk_ui_manager_new_merge_id (totem->ui_manager);
 
1404
        totem->subtitles_action_group = NULL;
 
1405
        totem->subtitles_ui_id = gtk_ui_manager_new_merge_id (totem->ui_manager);
 
1406
}
 
1407