~ubuntu-branches/ubuntu/saucy/parole/saucy-proposed

« back to all changes in this revision

Viewing changes to browser-plugin/media-plugin/parole-plugin-player.c

  • Committer: Bazaar Package Importer
  • Author(s): Yves-Alexis Perez, Lionel Le Folgoc, Yves-Alexis Perez
  • Date: 2011-04-24 16:09:19 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110424160919-rpjwaicrdb8f7un2
Tags: 0.2.0.6-1
[ Lionel Le Folgoc ]
* debian/control:
  - drop unneeded build-dep on xulrunner-dev.   closes: #594073
  - suggests a few useful gstreamer0.10 plugins.
  - build-depends on quilt.
* debian/patches:
  - 01_fix-implicit-dso-linking.patch: added, fixes FTBFS with binutils-gold.
  - series: added.                                            closes: #615760
* debian/rules: pass --with quilt to dh.

[ Yves-Alexis Perez ]
* New upstream release.
* Switch to 3.0 (quilt) source format.
* debian/control:
  - update standards version to 3.9.2.
  - drop browser-plugin-parole package.
  - drop quilt build-dep.
  - add build-dep on hardening-includes
  - bump xfce build-deps to 4.8.
* debian/parole.install updated.
* debian/rules:
  - use --fail-missing and manually remove spurious files.
  - drop quilt addon
  - pick build flags from dpkg-buildflags.
  - add -O1, -z,defs and --as-needed to LDFLAGS.
  - add hardening flags to build flags.
  - stop harcoding the shell to bash, it works fine now.      closes: #623830

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * * Copyright (C) 2009 Ali <aliov@xfce.org>
3
 
 *
4
 
 * Licensed under the GNU General Public License Version 2
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; either version 2 of the License, or
9
 
 * (at your option) any later version.
10
 
 *
11
 
 * This program is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
 * GNU General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU General Public License
17
 
 * along with this program; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
 
 */
20
 
 
21
 
#ifdef HAVE_CONFIG_H
22
 
#include <config.h>
23
 
#endif
24
 
 
25
 
#include <stdio.h>
26
 
#include <stdlib.h>
27
 
#include <string.h>
28
 
 
29
 
#include <gdk/gdkkeysyms.h>
30
 
 
31
 
#include <parole/parole.h>
32
 
 
33
 
#include <libxfce4util/libxfce4util.h>
34
 
#include <libxfcegui4/libxfcegui4.h>
35
 
 
36
 
#include "parole-plugin-player.h"
37
 
 
38
 
#include "gst/parole-gst.h"
39
 
#include "dbus/parole-dbus.h"
40
 
#include "common/parole-screensaver.h"
41
 
 
42
 
#define RESOURCE_FILE   "xfce4/parole/browser-plugin.rc"
43
 
 
44
 
/*
45
 
 * DBus Glib init
46
 
 */
47
 
static void parole_plugin_player_dbus_class_init (ParolePluginPlayerClass *klass);
48
 
static void parole_plugin_player_dbus_init       (ParolePluginPlayer *player);
49
 
 
50
 
static void parole_plugin_player_finalize     (GObject *object);
51
 
 
52
 
static void parole_plugin_player_set_property (GObject *object,
53
 
                                               guint prop_id,
54
 
                                               const GValue *value,
55
 
                                               GParamSpec *pspec);
56
 
static void parole_plugin_player_get_property (GObject *object,
57
 
                                               guint prop_id,
58
 
                                               GValue *value,
59
 
                                               GParamSpec *pspec);
60
 
 
61
 
#define PAROLE_PLUGIN_PLAYER_GET_PRIVATE(o) \
62
 
(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_PLUGIN_PLAYER, ParolePluginPlayerPrivate))
63
 
 
64
 
static GTimer *idle_timer = NULL;
65
 
static GThread *idle_thread = NULL;
66
 
 
67
 
struct ParolePluginPlayerPrivate
68
 
{
69
 
    DBusGConnection *bus;
70
 
    ParoleGst    *gst;
71
 
    GtkWidget    *window;
72
 
    GtkWidget    *plug;
73
 
    GtkWidget    *vbox;
74
 
    GtkWidget    *controls;
75
 
    GtkWidget    *play;
76
 
    GtkWidget    *range;
77
 
    GtkWidget    *full_screen;
78
 
    GtkWidget    *volume;
79
 
    GtkWidget    *buffering;
80
 
 
81
 
    GSList       *list;
82
 
 
83
 
    ParoleScreenSaver *saver;
84
 
    
85
 
    ParoleMediaState state;
86
 
    
87
 
    gboolean      fullscreen;
88
 
    
89
 
    gboolean      reload;
90
 
    gboolean      internal_range_change;
91
 
    gboolean      user_seeking;
92
 
    gboolean      terminate;
93
 
    gboolean      finished;
94
 
    gchar        *url;
95
 
    gulong        sig;
96
 
};
97
 
 
98
 
enum
99
 
{
100
 
    PROP_0,
101
 
    PROP_PLUG,
102
 
    PROP_URL
103
 
};
104
 
 
105
 
enum
106
 
{
107
 
    SIG_EXITING,
108
 
    SIG_READY,
109
 
    LAST_SIGNAL
110
 
};
111
 
 
112
 
static guint signals [LAST_SIGNAL] = { 0 };
113
 
    
114
 
G_DEFINE_TYPE (ParolePluginPlayer, parole_plugin_player, G_TYPE_OBJECT)
115
 
 
116
 
static void
117
 
parole_plugin_player_play (ParolePluginPlayer *player)
118
 
{
119
 
    if ( player->priv->terminate )
120
 
        return;
121
 
        
122
 
    player->priv->finished = FALSE;
123
 
    parole_gst_play_uri (player->priv->gst, player->priv->url, NULL);
124
 
}
125
 
 
126
 
static void
127
 
parole_plugin_player_set_fullscreen_button (ParolePluginPlayer *player)
128
 
{
129
 
    GtkWidget *img;
130
 
    
131
 
    g_object_get (G_OBJECT (player->priv->full_screen ),
132
 
                  "image", &img,
133
 
                  NULL);
134
 
                  
135
 
    if ( player->priv->fullscreen )
136
 
    {
137
 
        gtk_image_set_from_stock (GTK_IMAGE (img), GTK_STOCK_LEAVE_FULLSCREEN, GTK_ICON_SIZE_BUTTON);
138
 
        gtk_widget_set_tooltip_text (img, _("Leave fullscreen"));
139
 
    }
140
 
    else
141
 
    {
142
 
        gtk_image_set_from_stock (GTK_IMAGE (img), GTK_STOCK_FULLSCREEN, GTK_ICON_SIZE_BUTTON);
143
 
        gtk_widget_set_tooltip_text (img, _("Fullscreen"));
144
 
    }
145
 
    
146
 
    g_object_unref (G_OBJECT (img));
147
 
}
148
 
 
149
 
static void
150
 
parole_plugin_player_fullscreen (ParolePluginPlayer *player, gboolean fullscreen)
151
 
{
152
 
    if ( player->priv->fullscreen == fullscreen )
153
 
        return;
154
 
        
155
 
    player->priv->fullscreen = fullscreen;
156
 
    
157
 
    parole_plugin_player_set_fullscreen_button (player);
158
 
    
159
 
    if ( fullscreen )
160
 
    {
161
 
        gtk_widget_show (player->priv->window);
162
 
        gtk_widget_reparent (player->priv->vbox, player->priv->window);
163
 
        gtk_widget_show_all (player->priv->window);
164
 
        gtk_window_fullscreen (GTK_WINDOW (player->priv->window));
165
 
    }
166
 
    else
167
 
    {
168
 
        gtk_widget_hide (player->priv->window);
169
 
        gtk_widget_reparent (player->priv->vbox, player->priv->plug);
170
 
        gtk_window_unfullscreen (GTK_WINDOW (player->priv->window));
171
 
    }
172
 
}
173
 
 
174
 
static gboolean
175
 
read_entry_int (const gchar *entry, gint fallback)
176
 
{
177
 
    gint ret_val = fallback;
178
 
    gchar *file;
179
 
    XfceRc *rc;
180
 
    
181
 
    file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, RESOURCE_FILE, TRUE);
182
 
    rc = xfce_rc_simple_open (file, TRUE);
183
 
    g_free (file);
184
 
    
185
 
    if ( rc )
186
 
    {
187
 
        ret_val = xfce_rc_read_int_entry (rc, entry, fallback);
188
 
        xfce_rc_close (rc);
189
 
    }
190
 
    
191
 
    return ret_val;
192
 
}
193
 
 
194
 
static void
195
 
write_entry_int (const gchar *entry, gint value)
196
 
{
197
 
    gchar *file;
198
 
    XfceRc *rc;
199
 
    
200
 
    file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, RESOURCE_FILE, TRUE);
201
 
    rc = xfce_rc_simple_open (file, FALSE);
202
 
    g_free (file);
203
 
    
204
 
    xfce_rc_write_int_entry (rc, entry, value);
205
 
    xfce_rc_close (rc);
206
 
}
207
 
 
208
 
static void
209
 
parole_plugin_player_set_play_button_image (ParolePluginPlayer *player)
210
 
{
211
 
    GtkWidget *img;
212
 
    
213
 
    g_object_get (G_OBJECT (player->priv->play),
214
 
                  "image", &img,
215
 
                  NULL);
216
 
 
217
 
    if ( player->priv->state == PAROLE_MEDIA_STATE_PLAYING )
218
 
    {
219
 
        g_object_set (G_OBJECT (img),
220
 
                      "stock", GTK_STOCK_MEDIA_PAUSE,
221
 
                      NULL);
222
 
    }
223
 
    else
224
 
    {
225
 
        g_object_set (G_OBJECT (img),
226
 
                      "stock", GTK_STOCK_MEDIA_PLAY,
227
 
                      NULL);
228
 
                      
229
 
    }
230
 
    g_object_unref (img);
231
 
}
232
 
 
233
 
static void
234
 
parole_plugin_player_play_clicked_cb (ParolePluginPlayer *player)
235
 
{
236
 
    if ( player->priv->state == PAROLE_MEDIA_STATE_PLAYING )
237
 
        parole_gst_pause (player->priv->gst);
238
 
    else if ( player->priv->state == PAROLE_MEDIA_STATE_PAUSED )
239
 
        parole_gst_resume (player->priv->gst);
240
 
    else if ( player->priv->finished )
241
 
        parole_gst_stop (PAROLE_GST (player->priv->gst));
242
 
}
243
 
 
244
 
static void
245
 
parole_plugin_player_change_range_value (ParolePluginPlayer *player, gdouble value)
246
 
{
247
 
    if ( !player->priv->user_seeking )
248
 
    {
249
 
        player->priv->internal_range_change = TRUE;
250
 
    
251
 
        gtk_range_set_value (GTK_RANGE (player->priv->range), value);
252
 
 
253
 
        player->priv->internal_range_change = FALSE;
254
 
    }
255
 
}
256
 
 
257
 
static void
258
 
parole_plugin_player_media_state_cb (ParoleGst *gst, const ParoleStream *stream, 
259
 
                                     ParoleMediaState state, ParolePluginPlayer *player)
260
 
{
261
 
    gboolean has_video;
262
 
    
263
 
    
264
 
    g_object_get (G_OBJECT (stream),
265
 
                  "has-video", &has_video,
266
 
                  NULL);
267
 
    
268
 
    g_object_set (G_OBJECT (player->priv->full_screen),
269
 
                  "visible", has_video,
270
 
                  NULL);
271
 
    
272
 
    player->priv->state = state;
273
 
    parole_plugin_player_set_play_button_image (player);
274
 
    
275
 
    if ( has_video && state == PAROLE_MEDIA_STATE_PLAYING )
276
 
        parole_screen_saver_inhibit (player->priv->saver);
277
 
    else
278
 
        parole_screen_saver_uninhibit (player->priv->saver);
279
 
    
280
 
    if ( state == PAROLE_MEDIA_STATE_PLAYING )
281
 
    {
282
 
        gint64 duration;
283
 
        gboolean seekable;
284
 
        gboolean live;
285
 
        
286
 
        g_object_get (G_OBJECT (stream),
287
 
                      "seekable", &seekable,
288
 
                      "duration", &duration,
289
 
                      "live", &live,
290
 
                      NULL);
291
 
        
292
 
        gtk_widget_set_sensitive (player->priv->range, seekable);
293
 
        player->priv->internal_range_change = TRUE;
294
 
        if ( live || duration == 0 )
295
 
            parole_plugin_player_change_range_value (player, 0);
296
 
        else
297
 
            gtk_range_set_range (GTK_RANGE (player->priv->range), 0, duration);
298
 
        player->priv->internal_range_change = FALSE;
299
 
        
300
 
        gtk_widget_set_tooltip_text (GTK_WIDGET (player->priv->range), seekable ? NULL : _("Media stream is not seekable"));
301
 
    }
302
 
    else if ( state == PAROLE_MEDIA_STATE_PAUSED )
303
 
    {
304
 
        parole_plugin_player_change_range_value (player, 0);
305
 
    }
306
 
    else if ( state == PAROLE_MEDIA_STATE_STOPPED )
307
 
    {
308
 
        parole_plugin_player_change_range_value (player, 0);
309
 
        
310
 
        if ( player->priv->terminate )
311
 
        {
312
 
            gtk_main_quit ();
313
 
        }
314
 
        else if ( player->priv->reload )
315
 
        {
316
 
            player->priv->reload = FALSE;
317
 
            parole_plugin_player_play (player);
318
 
        }
319
 
        /* Play next item */
320
 
        else if ( player->priv->list != NULL && player->priv->url )
321
 
        {
322
 
            parole_plugin_player_play (player);
323
 
        }
324
 
        else if ( player->priv->finished )
325
 
        {
326
 
            player->priv->finished = FALSE;
327
 
        }
328
 
    }
329
 
    else if ( state == PAROLE_MEDIA_STATE_FINISHED )
330
 
    {
331
 
        parole_plugin_player_change_range_value (player, 0);
332
 
        player->priv->finished = TRUE;
333
 
        
334
 
        if ( player->priv->url )
335
 
        {
336
 
            g_free (player->priv->url);
337
 
            player->priv->url = NULL;
338
 
        }
339
 
                    
340
 
        if ( player->priv->list )
341
 
        {
342
 
            player->priv->list = player->priv->list->next;
343
 
            if ( player->priv->list->data )
344
 
            {
345
 
                ParoleFile *file = NULL;
346
 
                file = PAROLE_FILE (player->priv->list->data);
347
 
                if ( file )
348
 
                    player->priv->url = g_strdup (parole_file_get_uri (file));
349
 
            }
350
 
        }
351
 
        parole_gst_stop (PAROLE_GST (player->priv->gst));
352
 
    }
353
 
}
354
 
 
355
 
static gboolean 
356
 
parole_plugin_player_terminate (GtkWidget *widget, GdkEvent *ev, ParolePluginPlayer *player)
357
 
{
358
 
    //g_debug ("Delete event");
359
 
    parole_gst_terminate (player->priv->gst);
360
 
    g_signal_handler_disconnect (player->priv->plug, player->priv->sig);
361
 
    player->priv->terminate = TRUE;
362
 
    return TRUE;
363
 
}
364
 
 
365
 
static void
366
 
parole_plugin_player_range_value_changed (GtkRange *range, ParolePluginPlayer *player)
367
 
{
368
 
    gdouble value;
369
 
    
370
 
    if ( !player->priv->internal_range_change )
371
 
    {
372
 
        value = gtk_range_get_value (GTK_RANGE (range));
373
 
        player->priv->user_seeking = TRUE;
374
 
        parole_gst_seek (player->priv->gst, value);
375
 
        player->priv->user_seeking = FALSE;
376
 
    }
377
 
}
378
 
 
379
 
static gboolean
380
 
parole_plugin_player_range_button_release (GtkWidget *widget, GdkEventButton *ev, ParolePluginPlayer *player)
381
 
{
382
 
    ev->button = 2;
383
 
    
384
 
    player->priv->user_seeking = FALSE;
385
 
    
386
 
    return FALSE;
387
 
}
388
 
 
389
 
static gboolean
390
 
parole_plugin_player_range_button_press (GtkWidget *widget, GdkEventButton *ev, ParolePluginPlayer *player)
391
 
{
392
 
    ev->button = 2;
393
 
    
394
 
    player->priv->user_seeking = TRUE;
395
 
    
396
 
    return FALSE;
397
 
}
398
 
 
399
 
static void
400
 
parole_plugin_player_volume_changed_cb (GtkWidget *volume, gdouble value, ParolePluginPlayer *player)
401
 
{
402
 
    parole_gst_set_volume (player->priv->gst, value);
403
 
    write_entry_int ("volume", (gint) (value * 100));
404
 
}
405
 
 
406
 
static void
407
 
parole_plugin_player_media_progressed_cb (ParoleGst *gst, const ParoleStream *stream, 
408
 
                                          gint64 value, ParolePluginPlayer *player)
409
 
{
410
 
    
411
 
    if ( !player->priv->user_seeking && player->priv->state == PAROLE_MEDIA_STATE_PLAYING )
412
 
    {
413
 
        parole_plugin_player_change_range_value (player, value);
414
 
    }
415
 
}
416
 
 
417
 
static void
418
 
parole_plugin_player_reload (ParolePluginPlayer *player)
419
 
{
420
 
    player->priv->reload = TRUE;
421
 
    parole_gst_stop (player->priv->gst);
422
 
}
423
 
 
424
 
static void
425
 
parole_plugin_player_copy_url (ParolePluginPlayer *player)
426
 
{
427
 
    GtkClipboard *clipboard;
428
 
    
429
 
    clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
430
 
    gtk_clipboard_set_text (clipboard, player->priv->url, -1);
431
 
    clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
432
 
    gtk_clipboard_set_text (clipboard, player->priv->url, -1);
433
 
}
434
 
 
435
 
static void
436
 
parole_plugin_player_show_menu (ParolePluginPlayer *player, guint button, guint activate_time)
437
 
{
438
 
    GtkWidget *menu, *mi, *img;
439
 
    
440
 
    menu = gtk_menu_new ();
441
 
    
442
 
    /*
443
 
     * Reload 
444
 
     */
445
 
    mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_REFRESH, NULL);
446
 
    gtk_widget_show (mi);
447
 
    g_signal_connect_swapped (mi, "activate",
448
 
                              G_CALLBACK (parole_plugin_player_reload), player);
449
 
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
450
 
    
451
 
    
452
 
    /*
453
 
     * Copy url
454
 
     */
455
 
    mi = gtk_image_menu_item_new_with_label (_("Copy url"));
456
 
    img = gtk_image_new_from_stock (GTK_STOCK_COPY, GTK_ICON_SIZE_MENU);
457
 
    gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi),img);
458
 
    gtk_widget_show (mi);
459
 
    g_signal_connect_swapped (mi, "activate",
460
 
                              G_CALLBACK (parole_plugin_player_copy_url), player);
461
 
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
462
 
    
463
 
    
464
 
    g_signal_connect_swapped (menu, "selection-done",
465
 
                              G_CALLBACK (gtk_widget_destroy), menu);
466
 
    
467
 
    gtk_menu_popup (GTK_MENU (menu), 
468
 
                    NULL, NULL,
469
 
                    NULL, NULL,
470
 
                    button, activate_time);
471
 
}
472
 
 
473
 
static gboolean
474
 
parole_plugin_player_gst_widget_button_release (GtkWidget *widget, 
475
 
                                                GdkEventButton *ev, 
476
 
                                                ParolePluginPlayer *player)
477
 
{
478
 
    gboolean ret_val = FALSE;
479
 
    
480
 
    if ( ev->button == 3 )
481
 
    {
482
 
        parole_plugin_player_show_menu (player, ev->button, ev->time);
483
 
        ret_val = TRUE;
484
 
    }
485
 
    
486
 
    return ret_val;
487
 
}
488
 
 
489
 
static void
490
 
parole_plugin_player_fullscreen_clicked_cb (ParolePluginPlayer *player)
491
 
{
492
 
    parole_plugin_player_fullscreen (player, !player->priv->fullscreen);
493
 
}
494
 
 
495
 
static gboolean
496
 
parole_plugin_player_window_key_press_cb (GtkWidget *widget, GdkEventKey *ev, ParolePluginPlayer *player)
497
 
{
498
 
    gboolean ret_val = FALSE;
499
 
    
500
 
    switch (ev->keyval)
501
 
    {
502
 
        case GDK_F11:
503
 
        case GDK_f:
504
 
        case GDK_F:
505
 
            parole_plugin_player_fullscreen_clicked_cb (player);
506
 
            ret_val = TRUE;
507
 
            break;
508
 
        case GDK_Escape:
509
 
            parole_plugin_player_fullscreen (player, FALSE);
510
 
            ret_val = TRUE;
511
 
        default:
512
 
            break;
513
 
    }
514
 
 
515
 
    return ret_val;
516
 
}
517
 
 
518
 
static gboolean
519
 
parole_plugin_player_gst_widget_button_press (GtkWidget *widget, GdkEventButton *ev, ParolePluginPlayer *player)
520
 
{
521
 
    gboolean ret_val = FALSE;
522
 
 
523
 
    /* 
524
 
     * if full_screen widget is visible then we are playing 
525
 
     * video file so there is a point to go fullscreen.
526
 
     */
527
 
    if ( ev->type == GDK_2BUTTON_PRESS && GTK_WIDGET_VISIBLE (player->priv->full_screen) )
528
 
    {
529
 
        parole_plugin_player_fullscreen_clicked_cb (player);
530
 
        ret_val = TRUE;
531
 
    }
532
 
 
533
 
    return ret_val;
534
 
}
535
 
 
536
 
static gboolean
537
 
parole_plugin_player_window_delete_event_cb (ParolePluginPlayer *player)
538
 
{
539
 
    parole_plugin_player_fullscreen (player, FALSE);
540
 
    return TRUE;
541
 
}
542
 
 
543
 
static gpointer *check_idle_thread (gpointer data)
544
 
{
545
 
    ParolePluginPlayer *player;
546
 
    
547
 
    player = PAROLE_PLUGIN_PLAYER (data);
548
 
    
549
 
    do
550
 
    {
551
 
        g_usleep (1000000);
552
 
        if ( g_timer_elapsed (idle_timer, NULL ) > 60.f )
553
 
        {
554
 
            gtk_main_quit ();
555
 
        }
556
 
        
557
 
    } while ( player->priv->terminate == FALSE ); 
558
 
 
559
 
    return NULL;
560
 
}
561
 
 
562
 
static void
563
 
parole_plugin_player_dispose (GObject *object)
564
 
{
565
 
    ParolePluginPlayer *player;
566
 
    
567
 
    player = PAROLE_PLUGIN_PLAYER (object);
568
 
    
569
 
    G_OBJECT_CLASS (parole_plugin_player_parent_class)->dispose (object);
570
 
}
571
 
 
572
 
static void
573
 
parole_plugin_player_error_cb (ParoleGst *gst, const gchar *error, ParolePluginPlayer *player)
574
 
{
575
 
    player->priv->finished = TRUE;
576
 
    parole_screen_saver_uninhibit (player->priv->saver);
577
 
    g_warning ("player_error_cb : %s", error);
578
 
    
579
 
}
580
 
 
581
 
static void
582
 
parole_plugin_player_buffering_cb (ParoleGst *gst, const ParoleStream *stream, 
583
 
                                   gint percentage, ParolePluginPlayer *player)
584
 
{
585
 
    if ( percentage == 100 )
586
 
    {
587
 
        gtk_widget_hide (player->priv->buffering);
588
 
    }
589
 
    else
590
 
    {
591
 
        gchar *text;
592
 
        
593
 
        text = g_strdup_printf ("%s %d%%...", _("Buffering"), percentage);
594
 
        gtk_label_set_text (GTK_LABEL (player->priv->buffering), text);
595
 
        g_free (text);
596
 
        gtk_widget_show (player->priv->buffering);
597
 
    }
598
 
}
599
 
 
600
 
static void
601
 
parole_plugin_player_construct (GObject *object)
602
 
{
603
 
    ParolePluginPlayer *player;
604
 
    GtkObject *adj;
605
 
    GtkWidget *gstbox;
606
 
    GtkWidget *vbox;
607
 
    GtkWidget *hbox;
608
 
    GtkWidget *img;
609
 
    GtkWidget *sep;
610
 
    
611
 
    player = PAROLE_PLUGIN_PLAYER (object);
612
 
    
613
 
    vbox = gtk_vbox_new (FALSE, 0);
614
 
    
615
 
    /*
616
 
     * Gst Widget
617
 
     */
618
 
    gstbox = gtk_hbox_new (TRUE, 0);
619
 
    
620
 
    gtk_box_pack_start (GTK_BOX (gstbox), GTK_WIDGET (player->priv->gst), TRUE, TRUE, 0);
621
 
    gtk_box_pack_start (GTK_BOX (vbox), gstbox, TRUE, TRUE, 0);
622
 
    
623
 
    g_signal_connect (G_OBJECT (player->priv->gst), "media-state",
624
 
                      G_CALLBACK (parole_plugin_player_media_state_cb), player);
625
 
 
626
 
    g_signal_connect (G_OBJECT (player->priv->gst), "error",
627
 
                      G_CALLBACK (parole_plugin_player_error_cb), player);
628
 
    
629
 
    g_signal_connect (G_OBJECT (player->priv->gst), "buffering",
630
 
                      G_CALLBACK (parole_plugin_player_buffering_cb), player);
631
 
 
632
 
    g_signal_connect (G_OBJECT (player->priv->gst), "media-progressed",
633
 
                      G_CALLBACK (parole_plugin_player_media_progressed_cb), player);
634
 
 
635
 
    g_signal_connect_after (G_OBJECT (player->priv->gst), "button-release-event",
636
 
                            G_CALLBACK (parole_plugin_player_gst_widget_button_release), player);
637
 
 
638
 
    g_signal_connect_after (G_OBJECT (player->priv->gst), "button-press-event",
639
 
                            G_CALLBACK (parole_plugin_player_gst_widget_button_press), player);
640
 
 
641
 
    g_signal_connect (G_OBJECT (player->priv->gst), "error",
642
 
                      G_CALLBACK (parole_plugin_player_error_cb), player);
643
 
 
644
 
    hbox = gtk_hbox_new (FALSE, 0);
645
 
    /*
646
 
     * Play button
647
 
     */
648
 
    player->priv->play = gtk_button_new ();
649
 
    
650
 
    g_signal_connect_swapped (player->priv->play, "clicked",
651
 
                              G_CALLBACK (parole_plugin_player_play_clicked_cb), player);
652
 
    
653
 
    img = gtk_image_new_from_stock (GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
654
 
    
655
 
    g_object_set (G_OBJECT (player->priv->play),
656
 
                  "receives-default", FALSE,
657
 
                  "can-focus", FALSE,
658
 
                  "relief", GTK_RELIEF_NONE,
659
 
                  "image", img,
660
 
                  NULL);
661
 
                  
662
 
    gtk_box_pack_start (GTK_BOX (hbox), player->priv->play, 
663
 
                        FALSE, FALSE, 0);
664
 
                
665
 
    sep = gtk_vseparator_new ();
666
 
    gtk_box_pack_start (GTK_BOX (hbox), sep ,
667
 
                        FALSE, FALSE, 0);
668
 
    /*
669
 
     * Media range
670
 
     */
671
 
    player->priv->range = gtk_hscale_new (NULL);
672
 
    g_object_set (G_OBJECT (player->priv->range),
673
 
                  "draw-value", FALSE, 
674
 
                  "show-fill-level", TRUE,
675
 
                  NULL);
676
 
        
677
 
    gtk_box_pack_start (GTK_BOX (hbox), player->priv->range, 
678
 
                        TRUE, TRUE, 0);
679
 
    
680
 
    g_signal_connect (player->priv->range, "button-press-event",
681
 
                      G_CALLBACK (parole_plugin_player_range_button_press), player);
682
 
 
683
 
    g_signal_connect (player->priv->range, "button-release-event",
684
 
                      G_CALLBACK (parole_plugin_player_range_button_release), player);
685
 
                      
686
 
    g_signal_connect (player->priv->range, "value-changed",
687
 
                      G_CALLBACK (parole_plugin_player_range_value_changed), player);
688
 
                
689
 
    sep = gtk_vseparator_new ();
690
 
    gtk_box_pack_start (GTK_BOX (hbox), sep,
691
 
                        FALSE, FALSE, 0);
692
 
                        
693
 
    /*
694
 
     * Full screen button
695
 
     */
696
 
    player->priv->full_screen = gtk_button_new ();
697
 
    
698
 
    img = gtk_image_new ();
699
 
    
700
 
    g_object_set (G_OBJECT (player->priv->full_screen),
701
 
                  "receives-default", FALSE,
702
 
                  "can-focus", FALSE,
703
 
                  "relief", GTK_RELIEF_NONE,
704
 
                  "image", img,
705
 
                  NULL);
706
 
    parole_plugin_player_set_fullscreen_button (player);
707
 
    gtk_box_pack_start (GTK_BOX (hbox), player->priv->full_screen, 
708
 
                        FALSE, FALSE, 0);
709
 
    sep = gtk_vseparator_new ();
710
 
    gtk_box_pack_start (GTK_BOX (hbox), sep, 
711
 
                        FALSE, FALSE, 0);
712
 
    
713
 
    g_signal_connect_swapped (player->priv->full_screen, "clicked",
714
 
                              G_CALLBACK (parole_plugin_player_fullscreen_clicked_cb), player);
715
 
 
716
 
    /*
717
 
     * Volume button
718
 
     */
719
 
    adj = gtk_adjustment_new (0.,
720
 
                              0., 1., 1., 0., 0.);
721
 
    player->priv->volume = g_object_new (GTK_TYPE_VOLUME_BUTTON,
722
 
                                         "adjustment", adj,
723
 
                                         "size", GTK_ICON_SIZE_MENU,
724
 
                                         NULL);
725
 
    gtk_adjustment_set_value (GTK_ADJUSTMENT (adj), (gdouble) (read_entry_int ("volume", 100)/100.) );
726
 
    gtk_box_pack_start (GTK_BOX (hbox), player->priv->volume, 
727
 
                        FALSE, FALSE,  0);
728
 
        
729
 
    g_signal_connect (player->priv->volume, "value-changed",
730
 
                      G_CALLBACK (parole_plugin_player_volume_changed_cb), player);
731
 
    
732
 
    
733
 
    /*
734
 
     * buffering
735
 
     */
736
 
    player->priv->buffering = gtk_label_new (NULL);
737
 
    gtk_widget_set_no_show_all (player->priv->buffering, TRUE);
738
 
    gtk_widget_hide (player->priv->buffering);
739
 
    gtk_box_pack_start (GTK_BOX (vbox), player->priv->buffering, 
740
 
                        FALSE, FALSE, 0);
741
 
    
742
 
    gtk_box_pack_start (GTK_BOX (vbox), hbox, 
743
 
                        FALSE, FALSE, 0);
744
 
    gtk_container_add (GTK_CONTAINER (player->priv->plug), vbox);
745
 
    
746
 
    player->priv->sig = g_signal_connect (player->priv->plug, "delete-event",
747
 
                                          G_CALLBACK (parole_plugin_player_terminate), player);
748
 
                                             
749
 
    parole_plugin_player_change_range_value (player, 0);
750
 
    gtk_widget_set_sensitive (player->priv->range, FALSE);
751
 
    
752
 
    player->priv->vbox = vbox;
753
 
    
754
 
    g_signal_emit (player, signals [SIG_READY], 0);
755
 
    
756
 
    if ( player->priv->url )
757
 
        parole_plugin_player_play (player);
758
 
}
759
 
 
760
 
static void
761
 
parole_plugin_player_class_init (ParolePluginPlayerClass *klass)
762
 
{
763
 
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
764
 
 
765
 
    object_class->finalize = parole_plugin_player_finalize;
766
 
    object_class->dispose = parole_plugin_player_dispose;
767
 
 
768
 
    object_class->get_property = parole_plugin_player_get_property;
769
 
    object_class->set_property = parole_plugin_player_set_property;
770
 
 
771
 
    object_class->constructed = parole_plugin_player_construct;
772
 
    
773
 
    signals[SIG_EXITING] = 
774
 
        g_signal_new ("exiting",
775
 
                      PAROLE_TYPE_PLUGIN_PLAYER,
776
 
                      G_SIGNAL_RUN_LAST,
777
 
                      G_STRUCT_OFFSET (ParolePluginPlayerClass, exiting),
778
 
                      NULL, NULL,
779
 
                      g_cclosure_marshal_VOID__VOID,
780
 
                      G_TYPE_NONE, 0, G_TYPE_NONE);
781
 
    
782
 
    signals[SIG_READY] = 
783
 
        g_signal_new ("ready",
784
 
                      PAROLE_TYPE_PLUGIN_PLAYER,
785
 
                      G_SIGNAL_RUN_LAST,
786
 
                      G_STRUCT_OFFSET (ParolePluginPlayerClass, ready),
787
 
                      NULL, NULL,
788
 
                      g_cclosure_marshal_VOID__VOID,
789
 
                      G_TYPE_NONE, 0, G_TYPE_NONE);
790
 
    
791
 
    
792
 
    g_object_class_install_property (object_class,
793
 
                                     PROP_PLUG,
794
 
                                     g_param_spec_object ("plug",
795
 
                                                          NULL, NULL,
796
 
                                                          GTK_TYPE_PLUG,
797
 
                                                          G_PARAM_CONSTRUCT_ONLY | 
798
 
                                                          G_PARAM_READWRITE));
799
 
 
800
 
    g_object_class_install_property (object_class,
801
 
                                     PROP_URL,
802
 
                                     g_param_spec_string ("url",
803
 
                                                          NULL, NULL,
804
 
                                                          NULL,
805
 
                                                          G_PARAM_CONSTRUCT_ONLY | 
806
 
                                                          G_PARAM_READWRITE));
807
 
 
808
 
    g_type_class_add_private (klass, sizeof (ParolePluginPlayerPrivate));
809
 
    
810
 
    parole_plugin_player_dbus_class_init (klass);
811
 
}
812
 
 
813
 
static void
814
 
parole_plugin_player_init (ParolePluginPlayer *player)
815
 
{
816
 
    GError *error = NULL;
817
 
    
818
 
    player->priv = PAROLE_PLUGIN_PLAYER_GET_PRIVATE (player);
819
 
    
820
 
    player->priv->bus = parole_g_session_bus_get ();
821
 
    
822
 
    player->priv->gst  = NULL;
823
 
    player->priv->saver = parole_screen_saver_new ();
824
 
    player->priv->plug = NULL;
825
 
    player->priv->fullscreen = FALSE;
826
 
    player->priv->terminate = FALSE;
827
 
    player->priv->reload = FALSE;
828
 
    player->priv->user_seeking = FALSE;
829
 
    player->priv->internal_range_change = FALSE;
830
 
    player->priv->list = NULL;
831
 
    player->priv->state = PAROLE_MEDIA_STATE_STOPPED;
832
 
    
833
 
    player->priv->gst = PAROLE_GST (parole_gst_new (TRUE, NULL));
834
 
    
835
 
    player->priv->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
836
 
    gtk_window_set_keep_above (GTK_WINDOW (player->priv->window), TRUE);
837
 
    gtk_window_set_decorated (GTK_WINDOW (player->priv->window), FALSE);
838
 
    
839
 
    g_signal_connect_swapped (player->priv->window, "delete-event",
840
 
                              G_CALLBACK (parole_plugin_player_window_delete_event_cb), player);
841
 
    
842
 
    g_signal_connect (player->priv->window, "key-press-event",
843
 
                      G_CALLBACK (parole_plugin_player_window_key_press_cb), player);
844
 
    
845
 
    
846
 
    idle_timer = g_timer_new ();
847
 
    idle_thread = g_thread_create ((GThreadFunc)check_idle_thread, player, FALSE, &error);
848
 
    
849
 
    if ( error )
850
 
    {
851
 
        g_warning ("%s", error->message);
852
 
        g_error_free (error);
853
 
    }
854
 
 
855
 
    
856
 
    parole_plugin_player_dbus_init (player);
857
 
    
858
 
}
859
 
 
860
 
static void parole_plugin_player_set_property (GObject *object,
861
 
                                               guint prop_id,
862
 
                                               const GValue *value,
863
 
                                               GParamSpec *pspec)
864
 
{
865
 
    ParolePluginPlayer *player;
866
 
    player = PAROLE_PLUGIN_PLAYER (object);
867
 
 
868
 
    switch (prop_id)
869
 
    {
870
 
        case PROP_PLUG:
871
 
            player->priv->plug = GTK_WIDGET (g_value_get_object (value));
872
 
            break;
873
 
        case PROP_URL:
874
 
            player->priv->url = g_value_dup_string (value);
875
 
            break;
876
 
        default:
877
 
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
878
 
            break;
879
 
    }
880
 
}
881
 
 
882
 
static void parole_plugin_player_get_property (GObject *object,
883
 
                                               guint prop_id,
884
 
                                               GValue *value,
885
 
                                               GParamSpec *pspec)
886
 
{
887
 
    ParolePluginPlayer *player;
888
 
    player = PAROLE_PLUGIN_PLAYER (object);
889
 
 
890
 
    switch (prop_id)
891
 
    {
892
 
         default:
893
 
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
894
 
            break;
895
 
    }
896
 
}
897
 
 
898
 
static void
899
 
parole_plugin_player_finalize (GObject *object)
900
 
{
901
 
    ParolePluginPlayer *player;
902
 
 
903
 
    player = PAROLE_PLUGIN_PLAYER (object);
904
 
 
905
 
    //g_debug ("Finalize...");
906
 
 
907
 
    dbus_g_connection_unref (player->priv->bus);
908
 
 
909
 
    g_object_unref (player->priv->saver);
910
 
    
911
 
    if ( player->priv->url )
912
 
        g_free (player->priv->url);
913
 
 
914
 
    if ( player->priv->list )
915
 
    {
916
 
        g_slist_foreach (player->priv->list, (GFunc) g_object_unref, NULL);
917
 
        g_slist_free (player->priv->list);
918
 
    }
919
 
 
920
 
    G_OBJECT_CLASS (parole_plugin_player_parent_class)->finalize (object);
921
 
}
922
 
 
923
 
static gboolean parole_plugin_player_play_idle (gpointer data)
924
 
{
925
 
    ParolePluginPlayer *player;
926
 
    
927
 
    player = PAROLE_PLUGIN_PLAYER (data);
928
 
    
929
 
    parole_plugin_player_play (player);
930
 
    
931
 
    return FALSE;
932
 
}
933
 
 
934
 
static gboolean
935
 
parole_plugin_player_quit_idle (gpointer data)
936
 
{
937
 
    ParolePluginPlayer *player;
938
 
    
939
 
    player = PAROLE_PLUGIN_PLAYER (data);
940
 
    
941
 
    parole_gst_terminate (player->priv->gst);
942
 
    
943
 
    return FALSE;
944
 
}
945
 
 
946
 
static gboolean
947
 
parole_plugin_player_stop_idle (gpointer data)
948
 
{
949
 
    ParolePluginPlayer *player;
950
 
    
951
 
    player = PAROLE_PLUGIN_PLAYER (data);
952
 
    
953
 
    if (player->priv->gst)
954
 
        parole_gst_terminate (player->priv->gst);
955
 
        
956
 
    return FALSE;
957
 
}
958
 
 
959
 
ParolePluginPlayer *
960
 
parole_plugin_player_new (GtkWidget *plug, gchar *url)
961
 
{
962
 
    ParolePluginPlayer *player = NULL;
963
 
    
964
 
    player = g_object_new (PAROLE_TYPE_PLUGIN_PLAYER, 
965
 
                           "plug", plug, 
966
 
                           "url", url, 
967
 
                           NULL);
968
 
 
969
 
    return player;
970
 
}
971
 
 
972
 
void parole_plugin_player_exit (ParolePluginPlayer *player)
973
 
{
974
 
    player->priv->terminate = TRUE;
975
 
    parole_gst_terminate (player->priv->gst);
976
 
}
977
 
 
978
 
static gboolean parole_plugin_player_dbus_quit (ParolePluginPlayer *player,
979
 
                                                GError **error);
980
 
 
981
 
 
982
 
static gboolean parole_plugin_player_dbus_stop (ParolePluginPlayer *player,
983
 
                                                GError **error);
984
 
 
985
 
static gboolean parole_plugin_player_dbus_ping (ParolePluginPlayer *player,
986
 
                                                GError **error);
987
 
 
988
 
static gboolean parole_plugin_player_dbus_play_url (ParolePluginPlayer *player,
989
 
                                                    gchar *in_URL,
990
 
                                                    GError **error);
991
 
 
992
 
static gboolean parole_plugin_player_dbus_play_list (ParolePluginPlayer *player,
993
 
                                                     gchar *list,
994
 
                                                     GError **error);
995
 
 
996
 
#include "org.parole.media.plugin.h"
997
 
 
998
 
/*
999
 
 * DBus server implementation
1000
 
 */
1001
 
static void 
1002
 
parole_plugin_player_dbus_class_init (ParolePluginPlayerClass *klass)
1003
 
{
1004
 
    
1005
 
    dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
1006
 
                                     &dbus_glib_parole_gst_object_info);
1007
 
                                     
1008
 
}
1009
 
 
1010
 
static void
1011
 
parole_plugin_player_dbus_init (ParolePluginPlayer *player)
1012
 
{
1013
 
    dbus_g_connection_register_g_object (player->priv->bus,
1014
 
                                         "/org/Parole/Media/Plugin",
1015
 
                                         G_OBJECT (player));
1016
 
}
1017
 
 
1018
 
static gboolean
1019
 
parole_plugin_player_dbus_quit (ParolePluginPlayer *player,
1020
 
                                GError **error)
1021
 
{
1022
 
    //g_debug ("Quit message received");
1023
 
    player->priv->terminate = TRUE;
1024
 
    g_idle_add ((GSourceFunc) parole_plugin_player_quit_idle, player);
1025
 
    return TRUE;
1026
 
}
1027
 
 
1028
 
static gboolean 
1029
 
parole_plugin_player_dbus_stop (ParolePluginPlayer *player, GError **error)
1030
 
{
1031
 
    //g_debug ("Stop message received");
1032
 
    player->priv->terminate = TRUE;
1033
 
    g_idle_add ((GSourceFunc)parole_plugin_player_stop_idle, player);
1034
 
    
1035
 
    return TRUE;
1036
 
}
1037
 
 
1038
 
static gboolean parole_plugin_player_dbus_ping (ParolePluginPlayer *player,
1039
 
                                                GError **error)
1040
 
{
1041
 
    //g_debug ("Ping");
1042
 
    
1043
 
    if ( idle_timer )
1044
 
        g_timer_reset (idle_timer);
1045
 
        
1046
 
    return TRUE;
1047
 
}
1048
 
                                                
1049
 
static gboolean parole_plugin_player_dbus_play_url (ParolePluginPlayer *player,
1050
 
                                                    gchar *in_URL,
1051
 
                                                    GError **error)
1052
 
{
1053
 
    player->priv->url = g_strdup (in_URL);
1054
 
    //g_debug ("Playing url=%s", in_URL);
1055
 
    g_idle_add ((GSourceFunc) parole_plugin_player_play_idle, player);
1056
 
    return TRUE;
1057
 
}
1058
 
 
1059
 
static gboolean parole_plugin_player_dbus_play_list (ParolePluginPlayer *player,
1060
 
                                                     gchar *list,
1061
 
                                                     GError **error)
1062
 
{
1063
 
    player->priv->list = parole_pl_parser_parse_from_file_by_extension (list);
1064
 
    
1065
 
    if ( player->priv->list != NULL && g_slist_length (player->priv->list) != 0 )
1066
 
    {
1067
 
        ParoleFile *file;
1068
 
        file = g_slist_nth_data (player->priv->list, 0);
1069
 
        
1070
 
        player->priv->url = g_strdup (parole_file_get_uri (file));
1071
 
        //g_debug ("Playing url=%s", player->priv->url);
1072
 
        g_idle_add ((GSourceFunc) parole_plugin_player_play_idle, player);
1073
 
    }
1074
 
    
1075
 
    return TRUE;
1076
 
}