Logo Search packages:      
Sourcecode: parole version File versions  Download package

parole-plugin-player.c

/*
 * * Copyright (C) 2009 Ali <aliov@xfce.org>
 *
 * Licensed under the GNU General Public License Version 2
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <gdk/gdkkeysyms.h>

#include <parole/parole.h>

#include <libxfce4util/libxfce4util.h>
#include <libxfcegui4/libxfcegui4.h>

#include "parole-plugin-player.h"

#include "gst/parole-gst.h"
#include "dbus/parole-dbus.h"
#include "common/parole-screensaver.h"

#define RESOURCE_FILE   "xfce4/parole/browser-plugin.rc"

/*
 * DBus Glib init
 */
static void parole_plugin_player_dbus_class_init (ParolePluginPlayerClass *klass);
static void parole_plugin_player_dbus_init       (ParolePluginPlayer *player);

static void parole_plugin_player_finalize     (GObject *object);

static void parole_plugin_player_set_property (GObject *object,
                                     guint prop_id,
                                     const GValue *value,
                                     GParamSpec *pspec);
static void parole_plugin_player_get_property (GObject *object,
                                     guint prop_id,
                                     GValue *value,
                                     GParamSpec *pspec);

#define PAROLE_PLUGIN_PLAYER_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_PLUGIN_PLAYER, ParolePluginPlayerPrivate))

static GTimer *idle_timer = NULL;
static GThread *idle_thread = NULL;

struct ParolePluginPlayerPrivate
{
    DBusGConnection *bus;
    ParoleGst    *gst;
    GtkWidget    *window;
    GtkWidget    *plug;
    GtkWidget    *vbox;
    GtkWidget      *controls;
    GtkWidget      *play;
    GtkWidget      *range;
    GtkWidget    *full_screen;
    GtkWidget    *volume;
    GtkWidget      *buffering;

    GSList   *list;

    ParoleScreenSaver *saver;
    
    ParoleMediaState state;
    
    gboolean        fullscreen;
    
    gboolean        reload;
    gboolean      internal_range_change;
    gboolean      user_seeking;
    gboolean      terminate;
    gboolean        finished;
    gchar        *url;
    gulong        sig;
};

enum
{
    PROP_0,
    PROP_PLUG,
    PROP_URL
};

enum
{
    SIG_EXITING,
    SIG_READY,
    LAST_SIGNAL
};

static guint signals [LAST_SIGNAL] = { 0 };
    
G_DEFINE_TYPE (ParolePluginPlayer, parole_plugin_player, G_TYPE_OBJECT)

static void
parole_plugin_player_play (ParolePluginPlayer *player)
{
    if ( player->priv->terminate )
      return;
      
    player->priv->finished = FALSE;
    parole_gst_play_uri (player->priv->gst, player->priv->url, NULL);
}

static void
parole_plugin_player_set_fullscreen_button (ParolePluginPlayer *player)
{
    GtkWidget *img;
    
    g_object_get (G_OBJECT (player->priv->full_screen ),
              "image", &img,
              NULL);
              
    if ( player->priv->fullscreen )
    {
      gtk_image_set_from_stock (GTK_IMAGE (img), GTK_STOCK_LEAVE_FULLSCREEN, GTK_ICON_SIZE_BUTTON);
      gtk_widget_set_tooltip_text (img, _("Leave fullscreen"));
    }
    else
    {
      gtk_image_set_from_stock (GTK_IMAGE (img), GTK_STOCK_FULLSCREEN, GTK_ICON_SIZE_BUTTON);
      gtk_widget_set_tooltip_text (img, _("Fullscreen"));
    }
    
    g_object_unref (G_OBJECT (img));
}

static void
parole_plugin_player_fullscreen (ParolePluginPlayer *player, gboolean fullscreen)
{
    if ( player->priv->fullscreen == fullscreen )
      return;
      
    player->priv->fullscreen = fullscreen;
    
    parole_plugin_player_set_fullscreen_button (player);
    
    if ( fullscreen )
    {
      gtk_widget_show (player->priv->window);
      gtk_widget_reparent (player->priv->vbox, player->priv->window);
      gtk_widget_show_all (player->priv->window);
      gtk_window_fullscreen (GTK_WINDOW (player->priv->window));
    }
    else
    {
      gtk_widget_hide (player->priv->window);
      gtk_widget_reparent (player->priv->vbox, player->priv->plug);
      gtk_window_unfullscreen (GTK_WINDOW (player->priv->window));
    }
}

static gboolean
read_entry_int (const gchar *entry, gint fallback)
{
    gint ret_val = fallback;
    gchar *file;
    XfceRc *rc;
    
    file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, RESOURCE_FILE, TRUE);
    rc = xfce_rc_simple_open (file, TRUE);
    g_free (file);
    
    if ( rc )
    {
      ret_val = xfce_rc_read_int_entry (rc, entry, fallback);
      xfce_rc_close (rc);
    }
    
    return ret_val;
}

static void
write_entry_int (const gchar *entry, gint value)
{
    gchar *file;
    XfceRc *rc;
    
    file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, RESOURCE_FILE, TRUE);
    rc = xfce_rc_simple_open (file, FALSE);
    g_free (file);
    
    xfce_rc_write_int_entry (rc, entry, value);
    xfce_rc_close (rc);
}

static void
parole_plugin_player_set_play_button_image (ParolePluginPlayer *player)
{
    GtkWidget *img;
    
    g_object_get (G_OBJECT (player->priv->play),
                  "image", &img,
                  NULL);

    if ( player->priv->state == PAROLE_MEDIA_STATE_PLAYING )
    {
        g_object_set (G_OBJECT (img),
                      "stock", GTK_STOCK_MEDIA_PAUSE,
                      NULL);
    }
    else
    {
        g_object_set (G_OBJECT (img),
                      "stock", GTK_STOCK_MEDIA_PLAY,
                      NULL);
                      
    }
    g_object_unref (img);
}

static void
parole_plugin_player_play_clicked_cb (ParolePluginPlayer *player)
{
    if ( player->priv->state == PAROLE_MEDIA_STATE_PLAYING )
      parole_gst_pause (player->priv->gst);
    else if ( player->priv->state == PAROLE_MEDIA_STATE_PAUSED )
      parole_gst_resume (player->priv->gst);
    else if ( player->priv->finished )
      parole_gst_stop (PAROLE_GST (player->priv->gst));
}

static void
parole_plugin_player_change_range_value (ParolePluginPlayer *player, gdouble value)
{
    if ( !player->priv->user_seeking )
    {
      player->priv->internal_range_change = TRUE;
    
      gtk_range_set_value (GTK_RANGE (player->priv->range), value);

      player->priv->internal_range_change = FALSE;
    }
}

static void
parole_plugin_player_media_state_cb (ParoleGst *gst, const ParoleStream *stream, 
                             ParoleMediaState state, ParolePluginPlayer *player)
{
    gboolean has_video;
    
    
    g_object_get (G_OBJECT (stream),
              "has-video", &has_video,
              NULL);
    
    g_object_set (G_OBJECT (player->priv->full_screen),
              "visible", has_video,
              NULL);
    
    player->priv->state = state;
    parole_plugin_player_set_play_button_image (player);
    
    if ( has_video && state == PAROLE_MEDIA_STATE_PLAYING )
      parole_screen_saver_inhibit (player->priv->saver);
    else
      parole_screen_saver_uninhibit (player->priv->saver);
    
    if ( state == PAROLE_MEDIA_STATE_PLAYING )
    {
      gint64 duration;
      gboolean seekable;
      gboolean live;
      
      g_object_get (G_OBJECT (stream),
                  "seekable", &seekable,
                  "duration", &duration,
                  "live", &live,
                  NULL);
      
      gtk_widget_set_sensitive (player->priv->range, seekable);
      player->priv->internal_range_change = TRUE;
      if ( live || duration == 0 )
          parole_plugin_player_change_range_value (player, 0);
      else
          gtk_range_set_range (GTK_RANGE (player->priv->range), 0, duration);
      player->priv->internal_range_change = FALSE;
      
      gtk_widget_set_tooltip_text (GTK_WIDGET (player->priv->range), seekable ? NULL : _("Media stream is not seekable"));
    }
    else if ( state == PAROLE_MEDIA_STATE_PAUSED )
    {
      parole_plugin_player_change_range_value (player, 0);
    }
    else if ( state == PAROLE_MEDIA_STATE_STOPPED )
    {
      parole_plugin_player_change_range_value (player, 0);
      
      if ( player->priv->terminate )
      {
          gtk_main_quit ();
      }
      else if ( player->priv->reload )
      {
          player->priv->reload = FALSE;
          parole_plugin_player_play (player);
      }
      /* Play next item */
      else if ( player->priv->list != NULL && player->priv->url )
      {
          parole_plugin_player_play (player);
      }
      else if ( player->priv->finished )
      {
          player->priv->finished = FALSE;
      }
    }
    else if ( state == PAROLE_MEDIA_STATE_FINISHED )
    {
      parole_plugin_player_change_range_value (player, 0);
      player->priv->finished = TRUE;
      
      if ( player->priv->url )
      {
          g_free (player->priv->url);
          player->priv->url = NULL;
      }
                
      if ( player->priv->list )
      {
          player->priv->list = player->priv->list->next;
          if ( player->priv->list->data )
          {
            ParoleFile *file = NULL;
            file = PAROLE_FILE (player->priv->list->data);
            if ( file )
                player->priv->url = g_strdup (parole_file_get_uri (file));
          }
      }
      parole_gst_stop (PAROLE_GST (player->priv->gst));
    }
}

static gboolean 
parole_plugin_player_terminate (GtkWidget *widget, GdkEvent *ev, ParolePluginPlayer *player)
{
    //g_debug ("Delete event");
    parole_gst_terminate (player->priv->gst);
    g_signal_handler_disconnect (player->priv->plug, player->priv->sig);
    player->priv->terminate = TRUE;
    return TRUE;
}

static void
parole_plugin_player_range_value_changed (GtkRange *range, ParolePluginPlayer *player)
{
    gdouble value;
    
    if ( !player->priv->internal_range_change )
    {
      value = gtk_range_get_value (GTK_RANGE (range));
      player->priv->user_seeking = TRUE;
      parole_gst_seek (player->priv->gst, value);
      player->priv->user_seeking = FALSE;
    }
}

static gboolean
parole_plugin_player_range_button_release (GtkWidget *widget, GdkEventButton *ev, ParolePluginPlayer *player)
{
    ev->button = 2;
    
    player->priv->user_seeking = FALSE;
    
    return FALSE;
}

static gboolean
parole_plugin_player_range_button_press (GtkWidget *widget, GdkEventButton *ev, ParolePluginPlayer *player)
{
    ev->button = 2;
    
    player->priv->user_seeking = TRUE;
    
    return FALSE;
}

static void
parole_plugin_player_volume_changed_cb (GtkWidget *volume, gdouble value, ParolePluginPlayer *player)
{
    parole_gst_set_volume (player->priv->gst, value);
    write_entry_int ("volume", (gint) (value * 100));
}

static void
parole_plugin_player_media_progressed_cb (ParoleGst *gst, const ParoleStream *stream, 
                                gint64 value, ParolePluginPlayer *player)
{
    
    if ( !player->priv->user_seeking && player->priv->state == PAROLE_MEDIA_STATE_PLAYING )
    {
      parole_plugin_player_change_range_value (player, value);
    }
}

static void
parole_plugin_player_reload (ParolePluginPlayer *player)
{
    player->priv->reload = TRUE;
    parole_gst_stop (player->priv->gst);
}

static void
parole_plugin_player_copy_url (ParolePluginPlayer *player)
{
    GtkClipboard *clipboard;
    
    clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
    gtk_clipboard_set_text (clipboard, player->priv->url, -1);
    clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
    gtk_clipboard_set_text (clipboard, player->priv->url, -1);
}

static void
parole_plugin_player_show_menu (ParolePluginPlayer *player, guint button, guint activate_time)
{
    GtkWidget *menu, *mi, *img;
    
    menu = gtk_menu_new ();
    
    /*
     * Reload 
     */
    mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_REFRESH, NULL);
    gtk_widget_show (mi);
    g_signal_connect_swapped (mi, "activate",
                        G_CALLBACK (parole_plugin_player_reload), player);
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
    
    
    /*
     * Copy url
     */
    mi = gtk_image_menu_item_new_with_label (_("Copy url"));
    img = gtk_image_new_from_stock (GTK_STOCK_COPY, GTK_ICON_SIZE_MENU);
    gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi),img);
    gtk_widget_show (mi);
    g_signal_connect_swapped (mi, "activate",
                        G_CALLBACK (parole_plugin_player_copy_url), player);
    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
    
    
    g_signal_connect_swapped (menu, "selection-done",
                        G_CALLBACK (gtk_widget_destroy), menu);
    
    gtk_menu_popup (GTK_MENU (menu), 
                NULL, NULL,
                NULL, NULL,
                button, activate_time);
}

static gboolean
parole_plugin_player_gst_widget_button_release (GtkWidget *widget, 
                                    GdkEventButton *ev, 
                                    ParolePluginPlayer *player)
{
    gboolean ret_val = FALSE;
    
    if ( ev->button == 3 )
    {
      parole_plugin_player_show_menu (player, ev->button, ev->time);
      ret_val = TRUE;
    }
    
    return ret_val;
}

static void
parole_plugin_player_fullscreen_clicked_cb (ParolePluginPlayer *player)
{
    parole_plugin_player_fullscreen (player, !player->priv->fullscreen);
}

static gboolean
parole_plugin_player_window_key_press_cb (GtkWidget *widget, GdkEventKey *ev, ParolePluginPlayer *player)
{
    gboolean ret_val = FALSE;
    
    switch (ev->keyval)
    {
      case GDK_F11:
      case GDK_f:
      case GDK_F:
          parole_plugin_player_fullscreen_clicked_cb (player);
          ret_val = TRUE;
          break;
      case GDK_Escape:
          parole_plugin_player_fullscreen (player, FALSE);
          ret_val = TRUE;
      default:
          break;
    }

    return ret_val;
}

static gboolean
parole_plugin_player_gst_widget_button_press (GtkWidget *widget, GdkEventButton *ev, ParolePluginPlayer *player)
{
    gboolean ret_val = FALSE;

    /* 
     * if full_screen widget is visible then we are playing 
     * video file so there is a point to go fullscreen.
     */
    if ( ev->type == GDK_2BUTTON_PRESS && GTK_WIDGET_VISIBLE (player->priv->full_screen) )
    {
      parole_plugin_player_fullscreen_clicked_cb (player);
      ret_val = TRUE;
    }

    return ret_val;
}

static gboolean
parole_plugin_player_window_delete_event_cb (ParolePluginPlayer *player)
{
    parole_plugin_player_fullscreen (player, FALSE);
    return TRUE;
}

static gpointer *check_idle_thread (gpointer data)
{
    ParolePluginPlayer *player;
    
    player = PAROLE_PLUGIN_PLAYER (data);
    
    do
    {
      g_usleep (1000000);
      if ( g_timer_elapsed (idle_timer, NULL ) > 60.f )
      {
          gtk_main_quit ();
      }
      
    } while ( player->priv->terminate == FALSE ); 

    return NULL;
}

static void
parole_plugin_player_dispose (GObject *object)
{
    ParolePluginPlayer *player;
    
    player = PAROLE_PLUGIN_PLAYER (object);
    
    G_OBJECT_CLASS (parole_plugin_player_parent_class)->dispose (object);
}

static void
parole_plugin_player_error_cb (ParoleGst *gst, const gchar *error, ParolePluginPlayer *player)
{
    player->priv->finished = TRUE;
    parole_screen_saver_uninhibit (player->priv->saver);
    g_warning ("player_error_cb : %s", error);
    
}

static void
parole_plugin_player_buffering_cb (ParoleGst *gst, const ParoleStream *stream, 
                           gint percentage, ParolePluginPlayer *player)
{
    if ( percentage == 100 )
    {
      gtk_widget_hide (player->priv->buffering);
    }
    else
    {
      gchar *text;
      
      text = g_strdup_printf ("%s %d%%...", _("Buffering"), percentage);
      gtk_label_set_text (GTK_LABEL (player->priv->buffering), text);
      g_free (text);
      gtk_widget_show (player->priv->buffering);
    }
}

static void
parole_plugin_player_construct (GObject *object)
{
    ParolePluginPlayer *player;
    GtkObject *adj;
    GtkWidget *gstbox;
    GtkWidget *vbox;
    GtkWidget *hbox;
    GtkWidget *img;
    GtkWidget *sep;
    
    player = PAROLE_PLUGIN_PLAYER (object);
    
    vbox = gtk_vbox_new (FALSE, 0);
    
    /*
     * Gst Widget
     */
    gstbox = gtk_hbox_new (TRUE, 0);
    
    gtk_box_pack_start (GTK_BOX (gstbox), GTK_WIDGET (player->priv->gst), TRUE, TRUE, 0);
    gtk_box_pack_start (GTK_BOX (vbox), gstbox, TRUE, TRUE, 0);
    
    g_signal_connect (G_OBJECT (player->priv->gst), "media-state",
                  G_CALLBACK (parole_plugin_player_media_state_cb), player);

    g_signal_connect (G_OBJECT (player->priv->gst), "error",
                  G_CALLBACK (parole_plugin_player_error_cb), player);
    
    g_signal_connect (G_OBJECT (player->priv->gst), "buffering",
                  G_CALLBACK (parole_plugin_player_buffering_cb), player);

    g_signal_connect (G_OBJECT (player->priv->gst), "media-progressed",
                  G_CALLBACK (parole_plugin_player_media_progressed_cb), player);

    g_signal_connect_after (G_OBJECT (player->priv->gst), "button-release-event",
                      G_CALLBACK (parole_plugin_player_gst_widget_button_release), player);

    g_signal_connect_after (G_OBJECT (player->priv->gst), "button-press-event",
                      G_CALLBACK (parole_plugin_player_gst_widget_button_press), player);

    g_signal_connect (G_OBJECT (player->priv->gst), "error",
                  G_CALLBACK (parole_plugin_player_error_cb), player);

    hbox = gtk_hbox_new (FALSE, 0);
    /*
     * Play button
     */
    player->priv->play = gtk_button_new ();
    
    g_signal_connect_swapped (player->priv->play, "clicked",
                        G_CALLBACK (parole_plugin_player_play_clicked_cb), player);
    
    img = gtk_image_new_from_stock (GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
    
    g_object_set (G_OBJECT (player->priv->play),
              "receives-default", FALSE,
              "can-focus", FALSE,
              "relief", GTK_RELIEF_NONE,
              "image", img,
              NULL);
              
    gtk_box_pack_start (GTK_BOX (hbox), player->priv->play, 
                  FALSE, FALSE, 0);
            
    sep = gtk_vseparator_new ();
    gtk_box_pack_start (GTK_BOX (hbox), sep ,
                  FALSE, FALSE, 0);
    /*
     * Media range
     */
    player->priv->range = gtk_hscale_new (NULL);
    g_object_set (G_OBJECT (player->priv->range),
              "draw-value", FALSE, 
              "show-fill-level", TRUE,
              NULL);
      
    gtk_box_pack_start (GTK_BOX (hbox), player->priv->range, 
                  TRUE, TRUE, 0);
    
    g_signal_connect (player->priv->range, "button-press-event",
                  G_CALLBACK (parole_plugin_player_range_button_press), player);

    g_signal_connect (player->priv->range, "button-release-event",
                  G_CALLBACK (parole_plugin_player_range_button_release), player);
                  
    g_signal_connect (player->priv->range, "value-changed",
                  G_CALLBACK (parole_plugin_player_range_value_changed), player);
            
    sep = gtk_vseparator_new ();
    gtk_box_pack_start (GTK_BOX (hbox), sep,
                  FALSE, FALSE, 0);
                  
    /*
     * Full screen button
     */
    player->priv->full_screen = gtk_button_new ();
    
    img = gtk_image_new ();
    
    g_object_set (G_OBJECT (player->priv->full_screen),
              "receives-default", FALSE,
              "can-focus", FALSE,
              "relief", GTK_RELIEF_NONE,
              "image", img,
              NULL);
    parole_plugin_player_set_fullscreen_button (player);
    gtk_box_pack_start (GTK_BOX (hbox), player->priv->full_screen, 
                  FALSE, FALSE, 0);
    sep = gtk_vseparator_new ();
    gtk_box_pack_start (GTK_BOX (hbox), sep, 
                  FALSE, FALSE, 0);
    
    g_signal_connect_swapped (player->priv->full_screen, "clicked",
                        G_CALLBACK (parole_plugin_player_fullscreen_clicked_cb), player);

    /*
     * Volume button
     */
    adj = gtk_adjustment_new (0.,
                        0., 1., 1., 0., 0.);
    player->priv->volume = g_object_new (GTK_TYPE_VOLUME_BUTTON,
                               "adjustment", adj,
                               "size", GTK_ICON_SIZE_MENU,
                               NULL);
    gtk_adjustment_set_value (GTK_ADJUSTMENT (adj), (gdouble) (read_entry_int ("volume", 100)/100.) );
    gtk_box_pack_start (GTK_BOX (hbox), player->priv->volume, 
                  FALSE, FALSE,  0);
      
    g_signal_connect (player->priv->volume, "value-changed",
                  G_CALLBACK (parole_plugin_player_volume_changed_cb), player);
    
    
    /*
     * buffering
     */
    player->priv->buffering = gtk_label_new (NULL);
    gtk_widget_set_no_show_all (player->priv->buffering, TRUE);
    gtk_widget_hide (player->priv->buffering);
    gtk_box_pack_start (GTK_BOX (vbox), player->priv->buffering, 
                  FALSE, FALSE, 0);
    
    gtk_box_pack_start (GTK_BOX (vbox), hbox, 
                  FALSE, FALSE, 0);
    gtk_container_add (GTK_CONTAINER (player->priv->plug), vbox);
    
    player->priv->sig = g_signal_connect (player->priv->plug, "delete-event",
                                G_CALLBACK (parole_plugin_player_terminate), player);
                                   
    parole_plugin_player_change_range_value (player, 0);
    gtk_widget_set_sensitive (player->priv->range, FALSE);
    
    player->priv->vbox = vbox;
    
    g_signal_emit (player, signals [SIG_READY], 0);
    
    if ( player->priv->url )
      parole_plugin_player_play (player);
}

static void
parole_plugin_player_class_init (ParolePluginPlayerClass *klass)
{
    GObjectClass *object_class = G_OBJECT_CLASS (klass);

    object_class->finalize = parole_plugin_player_finalize;
    object_class->dispose = parole_plugin_player_dispose;

    object_class->get_property = parole_plugin_player_get_property;
    object_class->set_property = parole_plugin_player_set_property;

    object_class->constructed = parole_plugin_player_construct;
    
    signals[SIG_EXITING] = 
        g_signal_new ("exiting",
                      PAROLE_TYPE_PLUGIN_PLAYER,
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (ParolePluginPlayerClass, exiting),
                      NULL, NULL,
                      g_cclosure_marshal_VOID__VOID,
                      G_TYPE_NONE, 0, G_TYPE_NONE);
    
    signals[SIG_READY] = 
        g_signal_new ("ready",
                      PAROLE_TYPE_PLUGIN_PLAYER,
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (ParolePluginPlayerClass, ready),
                      NULL, NULL,
                      g_cclosure_marshal_VOID__VOID,
                      G_TYPE_NONE, 0, G_TYPE_NONE);
    
    
    g_object_class_install_property (object_class,
                                     PROP_PLUG,
                                     g_param_spec_object ("plug",
                                                          NULL, NULL,
                                                          GTK_TYPE_PLUG,
                                                          G_PARAM_CONSTRUCT_ONLY | 
                                            G_PARAM_READWRITE));

    g_object_class_install_property (object_class,
                                     PROP_URL,
                                     g_param_spec_string ("url",
                                                          NULL, NULL,
                                                          NULL,
                                                          G_PARAM_CONSTRUCT_ONLY | 
                                            G_PARAM_READWRITE));

    g_type_class_add_private (klass, sizeof (ParolePluginPlayerPrivate));
    
    parole_plugin_player_dbus_class_init (klass);
}

static void
parole_plugin_player_init (ParolePluginPlayer *player)
{
    GError *error = NULL;
    
    player->priv = PAROLE_PLUGIN_PLAYER_GET_PRIVATE (player);
    
    player->priv->bus = parole_g_session_bus_get ();
    
    player->priv->gst  = NULL;
    player->priv->saver = parole_screen_saver_new ();
    player->priv->plug = NULL;
    player->priv->fullscreen = FALSE;
    player->priv->terminate = FALSE;
    player->priv->reload = FALSE;
    player->priv->user_seeking = FALSE;
    player->priv->internal_range_change = FALSE;
    player->priv->list = NULL;
    player->priv->state = PAROLE_MEDIA_STATE_STOPPED;
    
    player->priv->gst = PAROLE_GST (parole_gst_new (TRUE, NULL));
    
    player->priv->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_keep_above (GTK_WINDOW (player->priv->window), TRUE);
    gtk_window_set_decorated (GTK_WINDOW (player->priv->window), FALSE);
    
    g_signal_connect_swapped (player->priv->window, "delete-event",
                        G_CALLBACK (parole_plugin_player_window_delete_event_cb), player);
    
    g_signal_connect (player->priv->window, "key-press-event",
                  G_CALLBACK (parole_plugin_player_window_key_press_cb), player);
    
    
    idle_timer = g_timer_new ();
    idle_thread = g_thread_create ((GThreadFunc)check_idle_thread, player, FALSE, &error);
    
    if ( error )
    {
        g_warning ("%s", error->message);
      g_error_free (error);
    }

    
    parole_plugin_player_dbus_init (player);
    
}

static void parole_plugin_player_set_property (GObject *object,
                                     guint prop_id,
                                     const GValue *value,
                                     GParamSpec *pspec)
{
    ParolePluginPlayer *player;
    player = PAROLE_PLUGIN_PLAYER (object);

    switch (prop_id)
    {
      case PROP_PLUG:
          player->priv->plug = GTK_WIDGET (g_value_get_object (value));
          break;
      case PROP_URL:
          player->priv->url = g_value_dup_string (value);
          break;
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
    }
}

static void parole_plugin_player_get_property (GObject *object,
                                     guint prop_id,
                                     GValue *value,
                                     GParamSpec *pspec)
{
    ParolePluginPlayer *player;
    player = PAROLE_PLUGIN_PLAYER (object);

    switch (prop_id)
    {
         default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
            break;
    }
}

static void
parole_plugin_player_finalize (GObject *object)
{
    ParolePluginPlayer *player;

    player = PAROLE_PLUGIN_PLAYER (object);

    //g_debug ("Finalize...");

    dbus_g_connection_unref (player->priv->bus);

    g_object_unref (player->priv->saver);
    
    if ( player->priv->url )
      g_free (player->priv->url);

    if ( player->priv->list )
    {
      g_slist_foreach (player->priv->list, (GFunc) g_object_unref, NULL);
      g_slist_free (player->priv->list);
    }

    G_OBJECT_CLASS (parole_plugin_player_parent_class)->finalize (object);
}

static gboolean parole_plugin_player_play_idle (gpointer data)
{
    ParolePluginPlayer *player;
    
    player = PAROLE_PLUGIN_PLAYER (data);
    
    parole_plugin_player_play (player);
    
    return FALSE;
}

static gboolean
parole_plugin_player_quit_idle (gpointer data)
{
    ParolePluginPlayer *player;
    
    player = PAROLE_PLUGIN_PLAYER (data);
    
    parole_gst_terminate (player->priv->gst);
    
    return FALSE;
}

static gboolean
parole_plugin_player_stop_idle (gpointer data)
{
    ParolePluginPlayer *player;
    
    player = PAROLE_PLUGIN_PLAYER (data);
    
    if (player->priv->gst)
      parole_gst_terminate (player->priv->gst);
      
    return FALSE;
}

ParolePluginPlayer *
parole_plugin_player_new (GtkWidget *plug, gchar *url)
{
    ParolePluginPlayer *player = NULL;
    
    player = g_object_new (PAROLE_TYPE_PLUGIN_PLAYER, 
                     "plug", plug, 
                     "url", url, 
                     NULL);

    return player;
}

void parole_plugin_player_exit (ParolePluginPlayer *player)
{
    player->priv->terminate = TRUE;
    parole_gst_terminate (player->priv->gst);
}

static gboolean parole_plugin_player_dbus_quit (ParolePluginPlayer *player,
                                    GError **error);


static gboolean parole_plugin_player_dbus_stop (ParolePluginPlayer *player,
                                    GError **error);

static gboolean parole_plugin_player_dbus_ping (ParolePluginPlayer *player,
                                    GError **error);

static gboolean parole_plugin_player_dbus_play_url (ParolePluginPlayer *player,
                                        gchar *in_URL,
                                        GError **error);

static gboolean parole_plugin_player_dbus_play_list (ParolePluginPlayer *player,
                                         gchar *list,
                                         GError **error);

#include "org.parole.media.plugin.h"

/*
 * DBus server implementation
 */
static void 
parole_plugin_player_dbus_class_init (ParolePluginPlayerClass *klass)
{
    
    dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
                                     &dbus_glib_parole_gst_object_info);
                                     
}

static void
parole_plugin_player_dbus_init (ParolePluginPlayer *player)
{
    dbus_g_connection_register_g_object (player->priv->bus,
                                         "/org/Parole/Media/Plugin",
                                         G_OBJECT (player));
}

static gboolean
parole_plugin_player_dbus_quit (ParolePluginPlayer *player,
                        GError **error)
{
    //g_debug ("Quit message received");
    player->priv->terminate = TRUE;
    g_idle_add ((GSourceFunc) parole_plugin_player_quit_idle, player);
    return TRUE;
}

static gboolean 
parole_plugin_player_dbus_stop (ParolePluginPlayer *player, GError **error)
{
    //g_debug ("Stop message received");
    player->priv->terminate = TRUE;
    g_idle_add ((GSourceFunc)parole_plugin_player_stop_idle, player);
    
    return TRUE;
}

static gboolean parole_plugin_player_dbus_ping (ParolePluginPlayer *player,
                                    GError **error)
{
    //g_debug ("Ping");
    
    if ( idle_timer )
      g_timer_reset (idle_timer);
      
    return TRUE;
}
                                    
static gboolean parole_plugin_player_dbus_play_url (ParolePluginPlayer *player,
                                        gchar *in_URL,
                                        GError **error)
{
    player->priv->url = g_strdup (in_URL);
    //g_debug ("Playing url=%s", in_URL);
    g_idle_add ((GSourceFunc) parole_plugin_player_play_idle, player);
    return TRUE;
}

static gboolean parole_plugin_player_dbus_play_list (ParolePluginPlayer *player,
                                         gchar *list,
                                         GError **error)
{
    player->priv->list = parole_pl_parser_parse_from_file_by_extension (list);
    
    if ( player->priv->list != NULL && g_slist_length (player->priv->list) != 0 )
    {
      ParoleFile *file;
      file = g_slist_nth_data (player->priv->list, 0);
      
      player->priv->url = g_strdup (parole_file_get_uri (file));
      //g_debug ("Playing url=%s", player->priv->url);
      g_idle_add ((GSourceFunc) parole_plugin_player_play_idle, player);
    }
    
    return TRUE;
}

Generated by  Doxygen 1.6.0   Back to index