[Goodies-commits] r7735 - in parole/trunk: . common data/interfaces docs docs/plugin-api parole plugins plugins/properties po

Ali Abdallah aliov at xfce.org
Thu Jul 16 17:03:07 CEST 2009


Author: aliov
Date: 2009-07-16 15:03:06 +0000 (Thu, 16 Jul 2009)
New Revision: 7735

Added:
   parole/trunk/common/
   parole/trunk/common/Makefile.am
   parole/trunk/common/parole-about.c
   parole/trunk/common/parole-about.h
   parole/trunk/common/parole-builder.c
   parole/trunk/common/parole-builder.h
   parole/trunk/docs/
   parole/trunk/docs/Makefile.am
   parole/trunk/docs/plugin-api/
   parole/trunk/docs/plugin-api/Makefile.am
   parole/trunk/docs/plugin-api/Parole-Plugins-docs.sgml
   parole/trunk/docs/plugin-api/Parole-Plugins-overrides.txt
   parole/trunk/docs/plugin-api/Parole-Plugins-sections.txt
   parole/trunk/docs/plugin-api/Parole-Plugins.types
   parole/trunk/docs/plugin-api/version.xml.in
   parole/trunk/parole/
   parole/trunk/parole/Makefile.am
   parole/trunk/parole/gmarshal.list
   parole/trunk/parole/main.c
   parole/trunk/parole/org.parole.media.list.xml
   parole/trunk/parole/parole-conf-dialog.c
   parole/trunk/parole/parole-conf-dialog.h
   parole/trunk/parole/parole-conf.c
   parole/trunk/parole/parole-conf.h
   parole/trunk/parole/parole-dbus.c
   parole/trunk/parole/parole-dbus.h
   parole/trunk/parole/parole-debug.c
   parole/trunk/parole/parole-debug.h
   parole/trunk/parole/parole-filters.c
   parole/trunk/parole/parole-filters.h
   parole/trunk/parole/parole-gst.c
   parole/trunk/parole/parole-gst.h
   parole/trunk/parole/parole-mediachooser.c
   parole/trunk/parole/parole-mediachooser.h
   parole/trunk/parole/parole-mediafile.c
   parole/trunk/parole/parole-mediafile.h
   parole/trunk/parole/parole-medialist.c
   parole/trunk/parole/parole-medialist.h
   parole/trunk/parole/parole-module.c
   parole/trunk/parole/parole-module.h
   parole/trunk/parole/parole-player.c
   parole/trunk/parole/parole-player.h
   parole/trunk/parole/parole-plugin.c
   parole/trunk/parole/parole-plugin.h
   parole/trunk/parole/parole-plugins-manager.c
   parole/trunk/parole/parole-plugins-manager.h
   parole/trunk/parole/parole-rc-utils.c
   parole/trunk/parole/parole-rc-utils.h
   parole/trunk/parole/parole-screensaver.c
   parole/trunk/parole/parole-screensaver.h
   parole/trunk/parole/parole-sidebar.c
   parole/trunk/parole/parole-sidebar.h
   parole/trunk/parole/parole-statusbar.c
   parole/trunk/parole/parole-statusbar.h
   parole/trunk/parole/parole-stream.c
   parole/trunk/parole/parole-stream.h
   parole/trunk/parole/parole-utils.c
   parole/trunk/parole/parole-utils.h
   parole/trunk/parole/parole-vis.c
   parole/trunk/parole/parole-vis.h
   parole/trunk/parole/parole.h
   parole/trunk/plugins/
   parole/trunk/plugins/Makefile.am
   parole/trunk/plugins/properties/
   parole/trunk/plugins/properties/Makefile.am
   parole/trunk/plugins/properties/stream-properties.c
Removed:
   parole/trunk/src/
Modified:
   parole/trunk/ChangeLog
   parole/trunk/Makefile.am
   parole/trunk/README
   parole/trunk/TODO
   parole/trunk/configure.ac.in
   parole/trunk/data/interfaces/Makefile.am
   parole/trunk/data/interfaces/parole.ui
   parole/trunk/po/POTFILES.in
   parole/trunk/po/parole-media-player.pot
Log:
	* plugins/properties: media properties plugin (Read only,
	needs to work the writing part with Taglib).
	* No need to install the interface files anymore.
	* Rename src dir to parole.
	* Gtk doc for plugin api (not yet complete).
	* parole/parole-player.c stop gst when the stream finishes 
	and no remaining media left in the list.
	* parole/parole-player.c rename the media file shown in the media list
	when we get a tag message from gst.
	* parole/parole-stream.c Handle tag messages.
	* parole/parole-module.{c,h} added a GTypeModule subclass
	* parole/parole-mediafile.c expose GObject properties.
	to handle plugins.
	* put some code in the common dir.
	* update POTFILES.in+README+TODO.

Modified: parole/trunk/ChangeLog
===================================================================
--- parole/trunk/ChangeLog	2009-07-16 15:03:04 UTC (rev 7734)
+++ parole/trunk/ChangeLog	2009-07-16 15:03:06 UTC (rev 7735)
@@ -1,3 +1,21 @@
+2009-07-16: Ali aliov at xfce.org
+        * Parole now has a simple plugin interface. (not yet complete).
+	* plugins/properties: media properties plugin (Read only,
+	needs to work the writing part with Taglib).
+	* No need to install the interface files anymore.
+	* Rename src dir to parole.
+	* Gtk doc for plugin api (not yet complete).
+	* parole/parole-player.c stop gst when the stream finishes 
+	and no remaining media left in the list.
+	* parole/parole-player.c rename the media file shown in the media list
+	when we get a tag message from gst.
+	* parole/parole-stream.c Handle tag messages.
+	* parole/parole-module.{c,h} added a GTypeModule subclass
+	* parole/parole-mediafile.c expose GObject properties.
+	to handle plugins.
+	* put some code in the common dir.
+	* update POTFILES.in+README+TODO.
+
 2009-07-08 9:00 Ali aliov at xfce.org
 	* data/interfaces/playlist.ui disable media list horizontal scrolling.
 	* po/POTFILES.in fix missing strings in the interface files.

Modified: parole/trunk/Makefile.am
===================================================================
--- parole/trunk/Makefile.am	2009-07-16 15:03:04 UTC (rev 7734)
+++ parole/trunk/Makefile.am	2009-07-16 15:03:06 UTC (rev 7735)
@@ -1,8 +1,12 @@
 SUBDIRS =  		\
-	  data		\
-	  src  		\
-	  po
+	data		\
+	common		\
+	parole 		\
+	plugins		\
+	docs		\
+	po
 
+
 EXTRA_DIST = \
 	intltool-extract.in \
 	intltool-merge.in \

Modified: parole/trunk/README
===================================================================
--- parole/trunk/README	2009-07-16 15:03:04 UTC (rev 7734)
+++ parole/trunk/README	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,26 @@
+What is it?
+===========
+
+Parole is a modern simple media player based on the GStreamer framework and written to fit well
+in the Xfce desktop. Parole features playback of local media files, DVD/CD and live streams.
+Parole is extensible via plugins, for a complete how to write a plugin for Parole see
+the Plugins API documentation+the plugins directory which contains some usefull examples.
+
+Required packages
+=================
+Parole depends on the following packages:
+
+ - Gtk 2.16 or above.
+ - Glib 2.16 or above.
+ - Gio 2.16 or above.
+ - DBus 0.60 or above.
+ - DBus glib 0.70 or above.
+ - libxfcegui4 4.6.0 or above.
+ - libxfce4util 4.6.0 or above
+
+How to report bugs?
+===================
+
+Bugs should be reported to the Xfce bug tracking system
+(http://bugzilla.xfce.org, product Parole). You will need to
+create an account for yourself.

Modified: parole/trunk/TODO
===================================================================
--- parole/trunk/TODO	2009-07-16 15:03:04 UTC (rev 7734)
+++ parole/trunk/TODO	2009-07-16 15:03:06 UTC (rev 7735)
@@ -1 +1,16 @@
+=== Media player ===
+* Currenlty the media player doesn't play DVD/CD.
+* Complete the shortcut keys.
+* Handle playlist(s), save/load.
+* Better statusbar information.
+* Encoding support for subtitles.
+* Configure plugins dialog to load/unload plugins.
+* Generate the data from the interfaces files with
+  exo-csource to avoid having to install them.
+* ...
 
+=== Plugins === 
+* Support for Taglib in the media properties plugin.
+* Write a youtube plugin.
+* Subtitle downloader.
+* ...?

Added: parole/trunk/common/Makefile.am
===================================================================
--- parole/trunk/common/Makefile.am	                        (rev 0)
+++ parole/trunk/common/Makefile.am	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,13 @@
+noinst_LTLIBRARIES = 			\
+	libparolecommon.la
+
+libparolecommon_la_SOURCES =		\
+	parole-builder.c		\
+	parole-builder.h		\
+	parole-about.c			\
+	parole-about.h
+
+libparolecommon_la_CFLAGS =		\
+	-I$(top_srcdir)/data		\
+	$(GTK_CFLAGS)			\
+	$(LIBXFCE4UTIL_CFLAGS)

Added: parole/trunk/common/parole-about.c
===================================================================
--- parole/trunk/common/parole-about.c	                        (rev 0)
+++ parole/trunk/common/parole-about.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,81 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <libxfce4util/libxfce4util.h>
+
+#include "parole-about.h"
+
+static void
+parole_link_browser (GtkAboutDialog *about, const gchar *link, gpointer data)
+{
+    gchar *cmd = g_strdup_printf ("%s %s","xfbrowser4", link);
+    g_spawn_command_line_async (cmd, NULL);
+    g_free (cmd);
+        
+}
+
+static void
+parole_link_mailto (GtkAboutDialog *about, const gchar *link, gpointer data)
+{
+    gchar *cmd = g_strdup_printf( "%s %s", "xdg-email", link);
+
+    g_spawn_command_line_async (cmd, NULL);
+    
+    g_free (cmd);
+}
+
+void  parole_about (const gchar *package)
+{
+    const gchar* authors[3] = 
+    {
+	"Ali Abdallah <aliov at xfce.org>", 
+	 NULL
+    };
+							    
+    static const gchar *documenters[] =
+    {
+	"Ali Abdallah <aliov at xfce.org>",
+	NULL,
+    };
+    
+
+    gtk_about_dialog_set_url_hook (parole_link_browser, NULL, NULL);
+    gtk_about_dialog_set_email_hook (parole_link_mailto, NULL, NULL);
+    
+    gtk_show_about_dialog (NULL,
+		           "authors", authors,
+			   "copyright", "Copyright \302\251 2009 Ali Abdallah",
+			   "destroy-with-parent", TRUE,
+			   "documenters", documenters,
+			   "license", XFCE_LICENSE_GPL,
+			   "name", package,
+			   "translator-credits", _("translator-credits"),
+			   "version", PACKAGE_VERSION,
+			   "website", "http://goodies.xfce.org",
+			   NULL);
+}

Added: parole/trunk/common/parole-about.h
===================================================================
--- parole/trunk/common/parole-about.h	                        (rev 0)
+++ parole/trunk/common/parole-about.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,29 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_ABOUT_H
+#define __PAROLE_ABOUT_H
+
+#include <gtk/gtk.h>
+
+void 		parole_about	(const gchar *package);
+
+
+#endif /* __PAROLE_ABOUT_H */

Added: parole/trunk/common/parole-builder.c
===================================================================
--- parole/trunk/common/parole-builder.c	                        (rev 0)
+++ parole/trunk/common/parole-builder.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,86 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 "interfaces/parole_ui.h"
+#include "parole-builder.h"
+
+GtkBuilder *
+parole_builder_get_main_interface (void)
+{
+    static gpointer parole_builder_object = NULL;
+    
+    if ( G_LIKELY (parole_builder_object != NULL) )
+    {
+	g_object_ref (parole_builder_object);
+    }
+    else
+    {
+	parole_builder_object = parole_builder_new_from_string (parole_ui, parole_ui_length);
+	g_object_add_weak_pointer (parole_builder_object, &parole_builder_object);
+    }
+    
+    return GTK_BUILDER (parole_builder_object);
+}
+
+GtkBuilder *parole_builder_new_from_file (const gchar *file)
+{
+    GtkBuilder *builder;
+    GError *error = NULL;
+
+    builder = gtk_builder_new ();
+    
+    gtk_builder_add_from_file (GTK_BUILDER (builder),
+			       file,
+			       &error);
+			       
+    if ( error )
+    {
+	g_critical ("%s", error->message);
+	g_error_free (error);
+    }
+    
+    return builder;
+}
+
+GtkBuilder *parole_builder_new_from_string (const gchar *ui, gsize length)
+{
+    GError *error = NULL;
+    GtkBuilder *builder;
+    
+    builder = gtk_builder_new ();
+    
+    gtk_builder_add_from_string (builder, ui, length, &error);
+    
+    if ( error )
+    {
+	g_critical ("%s", error->message);
+	g_error_free (error);
+    }
+    
+    return builder;
+}

Added: parole/trunk/common/parole-builder.h
===================================================================
--- parole/trunk/common/parole-builder.h	                        (rev 0)
+++ parole/trunk/common/parole-builder.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,38 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_BUILDER_H
+#define __PAROLE_BUILDER_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+GtkBuilder       	       *parole_builder_get_main_interface       (void);
+
+GtkBuilder		       *parole_builder_new_from_file   		(const gchar *file);
+
+GtkBuilder		       *parole_builder_new_from_string 		(const gchar *ui,
+									 gsize length);
+
+G_END_DECLS
+
+#endif /* __PAROLE_BUILDER_H */

Modified: parole/trunk/configure.ac.in
===================================================================
--- parole/trunk/configure.ac.in	2009-07-16 15:03:04 UTC (rev 7734)
+++ parole/trunk/configure.ac.in	2009-07-16 15:03:06 UTC (rev 7735)
@@ -1,4 +1,6 @@
 m4_define([intltool_minimum_version], [0.31])
+m4_define([parole_verinfo],  [0:1:0])
+m4_define([parole_version_api],  [0])
 m4_define([parole_version_major],  [0])
 m4_define([parole_version_minor],  [1])
 m4_define([parole_version_micro],  [0])
@@ -35,6 +37,20 @@
 AC_DISABLE_STATIC
 AC_PROG_LIBTOOL
 
+# ===================================================== #
+#               Version information                     #
+# ===================================================== #
+PAROLE_VERINFO=parole_verinfo()
+PAROLE_VERSION_API=parole_version_api()
+PAROLE_VERSION_MAJOR=parole_version_major()
+PAROLE_VERSION_MINOR=parole_version_minor()
+PAROLE_VERSION_MICRO=parole_version_micro()
+AC_SUBST([PAROLE_VERINFO])
+AC_SUBST([PAROLE_VERSION_API])
+AC_SUBST([PAROLE_VERSION_MAJOR])
+AC_SUBST([PAROLE_VERSION_MINOR])
+AC_SUBST([PAROLE_VERSION_MICRO])
+
 # ==================================================== #
 #   Check for headers needed for standard interfaces   #
 # ==================================================== #
@@ -92,28 +108,40 @@
 
 # Taken from Gnome system tools
 #=======================================================#
-#              Pixmaps and interface files              #
+#              Pixmaps  files              		#
 #=======================================================#
 if test "x${prefix}" = "xNONE"; then
   AC_DEFINE_UNQUOTED(PIXMAPS_DIR, "${ac_default_prefix}/${DATADIRNAME}/${PACKAGE}/pixmaps", [pixmaps directory])
   pixmapsdir="${ac_default_prefix}/${DATADIRNAME}/${PACKAGE}/pixmaps"
-  AC_DEFINE_UNQUOTED(INTERFACES_DIR, "${ac_default_prefix}/${DATADIRNAME}/${PACKAGE}/ui", [path where UI files will be installed])
-  interfacesdir="${ac_default_prefix}/${DATADIRNAME}/${PACKAGE}/ui"
 else
   AC_DEFINE_UNQUOTED(PIXMAPS_DIR, "${prefix}/${DATADIRNAME}/${PACKAGE}/pixmaps", [pixmaps directory])
   pixmapsdir="${prefix}/${DATADIRNAME}/${PACKAGE}/pixmaps"
-  AC_DEFINE_UNQUOTED(INTERFACES_DIR, "${prefix}/${DATADIRNAME}/${PACKAGE}/ui", [path where UI files will be installed])
-  interfacesdir="${prefix}/${DATADIRNAME}/${PACKAGE}/ui"
 fi
 
 AC_SUBST(pixmapsdir)
-AC_SUBST(interfacesdir)
 
 #=======================================================#
+#              Check plugins to build                   #
+#=======================================================#
+
+# Stream Properties plugin.
+#--------------------------
+AC_ARG_ENABLE([properties-plugin], AC_HELP_STRING([--disable-properties-plugin], [Don't build parole stream properties plugin]),
+  [ac_properties_plugin=$enableval], [ac_properties_plugin=yes])
+AC_MSG_CHECKING([whether to build the Parole stream properties plugin])
+AM_CONDITIONAL([PAROLE_PROPERTIES_PLUGIN], [test x"$ac_properties_plugin" = x"yes"])
+AC_MSG_RESULT([$ac_properties_plugin])
+
+#=======================================================#
 #              Check for debugging support              #
 #=======================================================#
 XDT_FEATURE_DEBUG
 
+#=======================================================#
+#              Check for Gtk doc	                #
+#=======================================================#
+GTK_DOC_CHECK(1.9)
+
 AC_OUTPUT([
 Makefile
 data/Makefile
@@ -122,20 +150,30 @@
 data/icons/Makefile
 data/mime/Makefile
 data/desktop/Makefile
-src/Makefile
+common/Makefile
+parole/Makefile
+plugins/Makefile
+plugins/properties/Makefile
+docs/Makefile
+docs/plugin-api/version.xml
+docs/plugin-api/Makefile
 po/Makefile.in
 ])
 
 echo "
---------------------------------------------------
+------------------------------------------------------
             Parole Media Player $VERSION
         ====================================
  
-        prefix:                 $prefix
-	interface_dir		$interfacesdir
-	pixmapsdir		$pixmapsdir
-	Notification		$LIBNOTIFY_FOUND
-        Debug        support:   $enable_debug
---------------------------------------------------
+        prefix:                 	$prefix
+	pixmapsdir:			$pixmapsdir
+	Notification:			$LIBNOTIFY_FOUND
+        Debug:   			$enable_debug
+	Building plugin api docs:       ${enable_gtk_doc}
+	
+	    Plugins to build:
+	    -----------------
+	Stream Properties plugin:       ${ac_properties_plugin}
+------------------------------------------------------
 
 Configuration finished, type make to compile"

Modified: parole/trunk/data/interfaces/Makefile.am
===================================================================
--- parole/trunk/data/interfaces/Makefile.am	2009-07-16 15:03:04 UTC (rev 7734)
+++ parole/trunk/data/interfaces/Makefile.am	2009-07-16 15:03:06 UTC (rev 7735)
@@ -5,8 +5,31 @@
 	mediachooser.ui				\
 	openlocation.ui
 
-interfaces_DATA = 				\
-	$(interfaces)
+interfaces_h = 					\
+	$(interfaces:.ui=_ui.h)
 
+if MAINTAINER_MODE
+BUILT_SOURCES = $(interfaces_h)
+
+parole_ui.h: parole.ui
+	exo-csource --static --strip-comments --strip-content --name=parole_ui $< > $@
+
+parole-settings_ui.h: parole-settings.ui
+	exo-csource --static --strip-comments --strip-content --name=parole_settings_ui $< > $@
+
+playlist_ui.h: playlist.ui
+	exo-csource --static --strip-comments --strip-content --name=playlist_ui $< > $@
+
+mediachooser_ui.h: mediachooser.ui
+	exo-csource --static --strip-comments --strip-content --name=mediachooser_ui $< > $@
+
+openlocation_ui.h: openlocation.ui
+	exo-csource --static --strip-comments --strip-content --name=openlocation_ui $< > $@
+endif
+
+DISTCLEANFILES =				\
+	$(interfaces_h)
+
 EXTRA_DIST =					\
-	$(interfaces)
\ No newline at end of file
+	$(interfaces)				\
+	$(interfaces_h)
\ No newline at end of file

Modified: parole/trunk/data/interfaces/parole.ui
===================================================================
--- parole/trunk/data/interfaces/parole.ui	2009-07-16 15:03:04 UTC (rev 7734)
+++ parole/trunk/data/interfaces/parole.ui	2009-07-16 15:03:06 UTC (rev 7735)
@@ -4,7 +4,7 @@
   <!-- interface-naming-policy project-wide -->
   <object class="GtkWindow" id="main-window">
     <property name="window_position">center</property>
-    <property name="default_width">720</property>
+    <property name="default_width">780</property>
     <property name="default_height">440</property>
     <signal name="destroy" handler="parole_player_destroy_cb"/>
     <signal name="key_press_event" handler="parole_player_key_press"/>
@@ -19,7 +19,7 @@
             <child>
               <object class="GtkMenuItem" id="file-menu">
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">_File</property>
+                <property name="label" translatable="yes">_Media</property>
                 <property name="use_underline">True</property>
                 <child type="submenu">
                   <object class="GtkMenu" id="menu1">
@@ -79,6 +79,13 @@
                   <object class="GtkMenu" id="menu4">
                     <property name="visible">True</property>
                     <child>
+                      <object class="GtkMenuItem" id="plugins-menu-item">
+                        <property name="visible">True</property>
+                        <property name="label" translatable="yes">Plugins</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                    </child>
+                    <child>
                       <object class="GtkImageMenuItem" id="preferences">
                         <property name="label">gtk-preferences</property>
                         <property name="visible">True</property>
@@ -123,11 +130,12 @@
                   <object class="GtkMenu" id="menu3">
                     <property name="visible">True</property>
                     <child>
-                      <object class="GtkImageMenuItem" id="imagemenuitem10">
+                      <object class="GtkImageMenuItem" id="about">
                         <property name="label">gtk-about</property>
                         <property name="visible">True</property>
                         <property name="use_underline">True</property>
                         <property name="use_stock">True</property>
+                        <signal name="activate" handler="parole_show_about"/>
                       </object>
                     </child>
                   </object>
@@ -363,12 +371,11 @@
                               </packing>
                             </child>
                             <child>
-                              <object class="GtkVBox" id="list-box">
+                              <object class="GtkNotebook" id="notebook-playlist">
                                 <property name="visible">True</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <placeholder/>
-                                </child>
+                                <property name="can_focus">True</property>
+                                <property name="scrollable">True</property>
+                                <property name="enable_popup">True</property>
                               </object>
                               <packing>
                                 <property name="resize">False</property>
@@ -392,62 +399,6 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkVBox" id="converter-box">
-                        <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkLabel" id="label1">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Nothing yet.</property>
-                          </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel" id="label2">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Audio converter</property>
-                      </object>
-                      <packing>
-                        <property name="position">1</property>
-                        <property name="tab_fill">False</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkVBox" id="recorder-box">
-                        <property name="visible">True</property>
-                        <property name="orientation">vertical</property>
-                        <child>
-                          <object class="GtkLabel" id="label4">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Nothing yet.</property>
-                          </object>
-                          <packing>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">2</property>
-                      </packing>
-                    </child>
-                    <child type="tab">
-                      <object class="GtkLabel" id="label3">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">Audio recorder</property>
-                      </object>
-                      <packing>
-                        <property name="position">2</property>
-                        <property name="tab_fill">False</property>
-                      </packing>
-                    </child>
-                    <child>
                       <object class="GtkVBox" id="albums-box">
                         <property name="visible">True</property>
                         <property name="orientation">vertical</property>
@@ -462,7 +413,7 @@
                         </child>
                       </object>
                       <packing>
-                        <property name="position">3</property>
+                        <property name="position">1</property>
                       </packing>
                     </child>
                     <child type="tab">
@@ -471,336 +422,12 @@
                         <property name="label" translatable="yes">Albums</property>
                       </object>
                       <packing>
-                        <property name="position">3</property>
+                        <property name="position">1</property>
                         <property name="tab_fill">False</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkNotebook" id="notebook1">
-                        <property name="visible">True</property>
-                        <property name="show_tabs">False</property>
-                        <property name="scrollable">True</property>
-                        <property name="group_id">0</property>
-                        <child>
-                          <object class="GtkHBox" id="playerbox1">
-                            <property name="visible">True</property>
-                            <child>
-                              <object class="GtkVBox" id="vbox5">
-                                <property name="visible">True</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkHBox" id="output1">
-                                    <property name="visible">True</property>
-                                    <child>
-                                      <placeholder/>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkVBox" id="vbox7">
-                                    <property name="visible">True</property>
-                                    <property name="orientation">vertical</property>
-                                    <property name="spacing">5</property>
-                                    <child>
-                                      <object class="GtkHScale" id="scale1">
-                                        <property name="visible">True</property>
-                                        <property name="sensitive">False</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="draw_value">False</property>
-                                      </object>
-                                      <packing>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkHBox" id="hbox4">
-                                        <property name="visible">True</property>
-                                        <property name="spacing">5</property>
-                                        <child>
-                                          <object class="GtkButton" id="back1">
-                                            <property name="visible">True</property>
-                                            <property name="sensitive">False</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                            <property name="image">image10</property>
-                                            <property name="relief">none</property>
-                                            <property name="focus_on_click">False</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkButton" id="stop1">
-                                            <property name="visible">True</property>
-                                            <property name="sensitive">False</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                            <property name="image">image11</property>
-                                            <property name="relief">none</property>
-                                            <property name="focus_on_click">False</property>
-                                            <accelerator key="s" signal="clicked"/>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkButton" id="play-pause1">
-                                            <property name="visible">True</property>
-                                            <property name="sensitive">False</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                            <property name="image">image12</property>
-                                            <property name="relief">none</property>
-                                            <property name="focus_on_click">False</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="position">2</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkButton" id="forward1">
-                                            <property name="visible">True</property>
-                                            <property name="sensitive">False</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="receives_default">True</property>
-                                            <property name="image">image13</property>
-                                            <property name="relief">none</property>
-                                            <property name="focus_on_click">False</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="position">3</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <placeholder/>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkVSeparator" id="vseparator1">
-                                <property name="visible">True</property>
-                                <property name="orientation">vertical</property>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="position">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkVBox" id="list-box1">
-                                <property name="visible">True</property>
-                                <property name="orientation">vertical</property>
-                                <child>
-                                  <object class="GtkScrolledWindow" id="scrolledwindow2">
-                                    <property name="visible">True</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="hscrollbar_policy">automatic</property>
-                                    <property name="vscrollbar_policy">automatic</property>
-                                    <child>
-                                      <object class="GtkTreeView" id="media-list1">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="headers_visible">False</property>
-                                        <property name="show_expanders">False</property>
-                                      </object>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkHBox" id="hbox5">
-                                    <property name="visible">True</property>
-                                    <child>
-                                      <object class="GtkButton" id="add-media1">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">True</property>
-                                        <property name="image">image14</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkButton" id="remove-media1">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">True</property>
-                                        <property name="image">image15</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkButton" id="media-up1">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">True</property>
-                                        <property name="image">image16</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkButton" id="media-down1">
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">True</property>
-                                        <property name="image">image17</property>
-                                      </object>
-                                      <packing>
-                                        <property name="expand">False</property>
-                                        <property name="position">3</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="fill">False</property>
-                                    <property name="position">1</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="expand">False</property>
-                                <property name="position">2</property>
-                              </packing>
-                            </child>
-                          </object>
-                        </child>
-                        <child type="tab">
-                          <object class="GtkLabel" id="Player1">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Media player</property>
-                          </object>
-                          <packing>
-                            <property name="tab_fill">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkVBox" id="converter-box1">
-                            <property name="visible">True</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel" id="label6">
-                                <property name="visible">True</property>
-                                <property name="label" translatable="yes">Nothing yet.</property>
-                              </object>
-                              <packing>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child type="tab">
-                          <object class="GtkLabel" id="label7">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Audio converter</property>
-                          </object>
-                          <packing>
-                            <property name="position">1</property>
-                            <property name="tab_fill">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkVBox" id="recorder-box1">
-                            <property name="visible">True</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel" id="label8">
-                                <property name="visible">True</property>
-                                <property name="label" translatable="yes">Nothing yet.</property>
-                              </object>
-                              <packing>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <child type="tab">
-                          <object class="GtkLabel" id="label9">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Audio recorder</property>
-                          </object>
-                          <packing>
-                            <property name="position">2</property>
-                            <property name="tab_fill">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkVBox" id="albums-box1">
-                            <property name="visible">True</property>
-                            <property name="orientation">vertical</property>
-                            <child>
-                              <object class="GtkLabel" id="label10">
-                                <property name="visible">True</property>
-                                <property name="label" translatable="yes">Nothing yet.</property>
-                              </object>
-                              <packing>
-                                <property name="position">0</property>
-                              </packing>
-                            </child>
-                          </object>
-                          <packing>
-                            <property name="position">3</property>
-                          </packing>
-                        </child>
-                        <child type="tab">
-                          <object class="GtkLabel" id="album1">
-                            <property name="visible">True</property>
-                            <property name="label" translatable="yes">Albums</property>
-                          </object>
-                          <packing>
-                            <property name="position">3</property>
-                            <property name="tab_fill">False</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <placeholder/>
-                        </child>
-                        <child type="tab">
-                          <placeholder/>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="position">4</property>
-                      </packing>
+                      <placeholder/>
                     </child>
                     <child type="tab">
                       <placeholder/>
@@ -843,38 +470,6 @@
     <property name="visible">True</property>
     <property name="stock">gtk-network</property>
   </object>
-  <object class="GtkImage" id="image10">
-    <property name="visible">True</property>
-    <property name="stock">gtk-media-previous</property>
-  </object>
-  <object class="GtkImage" id="image11">
-    <property name="visible">True</property>
-    <property name="stock">gtk-media-stop</property>
-  </object>
-  <object class="GtkImage" id="image12">
-    <property name="visible">True</property>
-    <property name="stock">gtk-media-play</property>
-  </object>
-  <object class="GtkImage" id="image13">
-    <property name="visible">True</property>
-    <property name="stock">gtk-media-next</property>
-  </object>
-  <object class="GtkImage" id="image14">
-    <property name="visible">True</property>
-    <property name="stock">gtk-add</property>
-  </object>
-  <object class="GtkImage" id="image15">
-    <property name="visible">True</property>
-    <property name="stock">gtk-remove</property>
-  </object>
-  <object class="GtkImage" id="image16">
-    <property name="visible">True</property>
-    <property name="stock">gtk-go-up</property>
-  </object>
-  <object class="GtkImage" id="image17">
-    <property name="visible">True</property>
-    <property name="stock">gtk-go-down</property>
-  </object>
   <object class="GtkImage" id="image6">
     <property name="visible">True</property>
     <property name="stock">gtk-media-previous</property>

Added: parole/trunk/docs/Makefile.am
===================================================================
--- parole/trunk/docs/Makefile.am	                        (rev 0)
+++ parole/trunk/docs/Makefile.am	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,2 @@
+SUBDIRS = 		\
+	plugin-api
\ No newline at end of file

Added: parole/trunk/docs/plugin-api/Makefile.am
===================================================================
--- parole/trunk/docs/plugin-api/Makefile.am	                        (rev 0)
+++ parole/trunk/docs/plugin-api/Makefile.am	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,101 @@
+## Process this file with automake to produce Makefile.in
+
+AUTOMAKE_OPTIONS = 1.7
+
+# This is a blank Makefile.am for using gtk-doc.
+# Copy this to your project's API docs directory and modify the variables to
+# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
+# of using the various options.
+
+# The name of the module, e.g. 'glib'.
+DOC_MODULE=Parole-Plugins
+
+# The top-level SGML file. You can change this if you want to.
+DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
+
+# The directory containing the source code. Relative to $(srcdir).
+# gtk-doc will search all .c & .h files beneath here for inline comments
+# documenting the functions and macros.
+# e.g. DOC_SOURCE_DIR=../../../gtk
+DOC_SOURCE_DIR=../../parole
+
+# Extra options to supply to gtkdoc-scan.
+# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
+SCAN_OPTIONS=--ignore-headers=config.h --rebuild-types
+
+# Extra options to supply to gtkdoc-mkdb.
+# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
+MKDB_OPTIONS=--sgml-mode --output-format=xml
+
+# Extra options to supply to gtkdoc-mktmpl
+# e.g. MKTMPL_OPTIONS=--only-section-tmpl
+MKTMPL_OPTIONS=
+
+# Extra options to supply to gtkdoc-mkhtml
+MKHTML_OPTIONS=
+
+# Extra options to supply to gtkdoc-fixref. Not normally needed.
+# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
+FIXXREF_OPTIONS=
+
+# Used for dependencies. The docs will be rebuilt if any of these change.
+# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
+# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
+CFILE_GLOB=$(top_srcdir)/parole/*.c
+HFILE_GLOB=$(top_srcdir)/parole/*.h
+
+# Header files to ignore when scanning.
+# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
+IGNORE_HFILES=
+	parole-player.h				\
+	parole-gst.h				\
+	parole-vis.h				\
+	parole-statusbar.h			\
+	parole-builder.h			\
+	parole-mediachooser.h			\
+	parole-filters.h			\
+	parole-screensaver.h			\
+	parole-conf.h				\
+	parole-conf-dialog.h			\
+	parole-rc-utils.h			\
+	parole-utils.h				\
+	parole-dbus.h				\
+	parole-debug.h				\
+	parole-plugin-manager.h
+
+# Images to copy into HTML directory.
+# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
+HTML_IMAGES=
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
+content_files= 			\
+	version.xml
+
+# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
+# Only needed if you are using gtkdoc-scangobj to dynamically query widget
+# signals and properties.
+# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
+# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
+GTKDOC_CFLAGS=                  \
+	$(GTK_CFLAGS)		\
+        $(GLIB_CFLAGS)          \
+        $(GOBJECT_CFLAGS)       \
+        -I$(top_srcdir)/parole  \
+        -I$(top_builddir)/parole
+
+GTKDOC_LIBS=                    \
+	$(GTK_LIBS)		\
+        $(GLIB_LIBS)            \
+        $(GOBJECT_LIBS)		\
+	$(top_builddir)/parole/libparole.la
+
+if ENABLE_GTK_DOC
+include $(top_srcdir)/gtk-doc.make
+else
+EXTRA_DIST=
+endif
+
+EXTRA_DIST +=			\
+	version.xml.in
+

Added: parole/trunk/docs/plugin-api/Parole-Plugins-docs.sgml
===================================================================
--- parole/trunk/docs/plugin-api/Parole-Plugins-docs.sgml	                        (rev 0)
+++ parole/trunk/docs/plugin-api/Parole-Plugins-docs.sgml	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd"
+[
+  <!ENTITY % local.common.attrib "xmlns:xi  CDATA  #FIXED 'http://www.w3.org/2003/XInclude'">
+  <!ENTITY version SYSTEM "version.xml">
+  <!ENTITY date "July 2009">
+]>
+<book id="index">
+  <bookinfo>
+    <title>Parole Plugins Reference Manual</title>
+    <releaseinfo>
+      for Parole-Plugins &version;
+    </releaseinfo>
+    <pubdate>&date;</pubdate>
+    
+    <copyright>
+      <year>2009</year>
+      <holder>Ali Abdallah</holder>
+    </copyright>
+
+    <legalnotice id="legalnotice">
+      <para>
+        Permission is granted to copy, distribute and/or modify this document
+        under the terms of the GNU Free Documentation License, Version 1.1 or
+        any later version published by the Free Software Foundation; with no
+        Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
+        Texts. The complete license text is available from the <ulink
+        type="http" url="http://www.gnu.org/">Free Software Foundation</ulink>.
+      </para>
+    </legalnotice>
+    
+  </bookinfo>
+
+  <chapter>
+    <title>Parole Plugins Overview</title>
+        <xi:include href="xml/parole.xml"/>
+
+        <xi:include href="xml/parole-plugin.xml"/>
+	<xi:include href="xml/parole-mediafile.xml"/>
+	<xi:include href="xml/parole-stream.xml"/>
+  </chapter>
+  
+  <index id="api-index-full">
+    <title>API Index</title>
+    <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
+  </index>
+
+  <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
+</book>

Added: parole/trunk/docs/plugin-api/Parole-Plugins-sections.txt
===================================================================
--- parole/trunk/docs/plugin-api/Parole-Plugins-sections.txt	                        (rev 0)
+++ parole/trunk/docs/plugin-api/Parole-Plugins-sections.txt	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,311 @@
+<SECTION>
+<FILE>parole-plugin</FILE>
+ParolePluginContainer
+ParoleState
+<TITLE>ParolePlugin</TITLE>
+ParolePlugin
+parole_plugin_new
+parole_plugin_get_main_window
+parole_plugin_pack_widget
+parole_plugin_play_uri
+parole_plugin_play_file
+parole_plugin_pause_playing
+parole_plugin_resume
+parole_plugin_stop_playing
+parole_plugin_seek
+<SUBSECTION Standard>
+PAROLE_PLUGIN
+PAROLE_IS_PLUGIN
+PAROLE_TYPE_PLUGIN
+parole_plugin_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-mediachooser</FILE>
+ParoleMediaChooserPrivate
+media_files_opened
+media_file_opened
+parole_media_chooser_open_local
+parole_media_chooser_open_location
+<SUBSECTION Standard>
+PAROLE_MEDIA_CHOOSER
+PAROLE_IS_MEDIA_CHOOSER
+PAROLE_TYPE_MEDIA_CHOOSER
+parole_media_chooser_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-plugins-manager</FILE>
+ParolePluginsManagerPrivate
+parole_plugins_manager_new
+parole_plugins_manager_load_plugins
+parole_plugins_manager_pack
+<SUBSECTION Standard>
+PAROLE_PLUGINS_MANAGER
+PAROLE_IS_PLUGINS_MANAGER
+PAROLE_TYPE_PLUGINS_MANAGER
+parole_plugins_manager_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-module</FILE>
+ParoleModulePrivate
+constructor
+parole_module_new
+<SUBSECTION Standard>
+PAROLE_MODULE
+PAROLE_IS_MODULE
+PAROLE_TYPE_MODULE
+parole_module_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-screensaver</FILE>
+PAROLE_SCREEN_SAVER
+ParoleScreenSaverPrivate
+parole_screen_saver_new
+parole_screen_saver_inhibit
+parole_screen_saver_uninhibit
+<SUBSECTION Standard>
+PAROLE_IS_SCREENSAVER
+PAROLE_TYPE_SCREENSAVER
+parole_screen_saver_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-sidebar</FILE>
+ParoleSidebarPrivate
+parole_sidebar_new
+parole_sidebar_set_visible
+<SUBSECTION Standard>
+PAROLE_SIDEBAR
+PAROLE_IS_SIDEBAR
+PAROLE_TYPE_SIDEBAR
+parole_sidebar_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-gst</FILE>
+ParoleMediaState
+ParoleGstPrivate
+media_state
+media_progressed
+buffering
+media_tag
+error
+parole_gst_new
+parole_gst_play_file
+parole_gst_pause
+parole_gst_resume
+parole_gst_stop
+parole_gst_null_state
+parole_gst_seek
+parole_gst_set_volume
+parole_gst_get_volume
+<SUBSECTION Standard>
+PAROLE_GST
+PAROLE_IS_GST
+PAROLE_TYPE_GST
+parole_gst_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-mediafile</FILE>
+<TITLE>ParoleMediaFile</TITLE>
+ParoleMediaFile
+parole_media_file_new
+parole_media_file_get_file_name
+parole_media_file_get_display_name
+parole_media_file_get_uri
+parole_media_file_get_content_type
+<SUBSECTION Standard>
+PAROLE_MEDIA_FILE
+PAROLE_IS_MEDIA_FILE
+PAROLE_TYPE_MEDIA_FILE
+parole_media_file_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-player</FILE>
+ParolePlayerPrivate
+parole_player_new
+parole_player_get_media_list
+<SUBSECTION Standard>
+PAROLE_PLAYER
+PAROLE_IS_PLAYER
+PAROLE_TYPE_PLAYER
+parole_player_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-medialist</FILE>
+ParoleMediaListPrivate
+media_activated
+media_cursor_changed
+parole_media_list_new
+parole_media_list_get_selected_row
+parole_media_list_get_next_row
+parole_media_list_set_row_pixbuf
+parole_media_list_set_row_name
+parole_media_list_open
+parole_media_list_open_location
+parole_media_list_add_files
+<SUBSECTION Standard>
+PAROLE_MEDIA_LIST
+PAROLE_IS_MEDIA_LIST
+PAROLE_TYPE_MEDIA_LIST
+parole_media_list_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-conf-dialog</FILE>
+ParoleConfDialogPrivate
+parole_conf_dialog_new
+parole_conf_dialog_open
+<SUBSECTION Standard>
+PAROLE_CONF_DIALOG
+PAROLE_IS_CONF_DIALOG
+PAROLE_TYPE_CONF_DIALOG
+parole_conf_dialog_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-statusbar</FILE>
+ParoleStatusbarPrivate
+parole_statusbar_new
+parole_statusbar_set_text
+parole_statusbar_set_duration
+parole_statusbar_set_position
+parole_statusbar_set_buffering
+parole_statusbar_set_visible
+<SUBSECTION Standard>
+PAROLE_STATUSBAR
+PAROLE_IS_STATUSBAR
+PAROLE_TYPE_STATUSBAR
+parole_statusbar_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-conf</FILE>
+ParoleConfPrivate
+parole_conf_new
+<SUBSECTION Standard>
+PAROLE_CONF
+PAROLE_IS_CONF
+PAROLE_TYPE_CONF
+parole_conf_get_type
+</SECTION>
+
+<SECTION>
+<FILE>parole-stream</FILE>
+<TITLE>ParoleStream</TITLE>
+ParoleStream
+parole_stream_new
+parole_stream_init_properties
+<SUBSECTION Standard>
+PAROLE_STREAM
+PAROLE_IS_STREAM
+PAROLE_TYPE_STREAM
+parole_stream_get_type
+</SECTION>
+
+<SECTION>
+<FILE>enum-gtypes</FILE>
+parole_media_state_get_type
+ENUM_GTYPE_MEDIA_STATE
+parole_plugin_container_get_type
+ENUM_GTYPE_PLUGIN_CONTAINER
+parole_state_get_type
+ENUM_GTYPE_STATE
+</SECTION>
+
+<SECTION>
+<FILE>parole-rc-utils</FILE>
+parole_rc_write_entry_bool
+parole_rc_write_entry_int
+parole_rc_write_entry_string
+parole_rc_read_entry_bool
+parole_rc_read_entry_int
+parole_rc_read_entry_string
+</SECTION>
+
+<SECTION>
+<FILE>org.parole.media.list</FILE>
+g_marshal_value_peek_boolean
+g_marshal_value_peek_char
+g_marshal_value_peek_uchar
+g_marshal_value_peek_int
+g_marshal_value_peek_uint
+g_marshal_value_peek_long
+g_marshal_value_peek_ulong
+g_marshal_value_peek_int64
+g_marshal_value_peek_uint64
+g_marshal_value_peek_enum
+g_marshal_value_peek_flags
+g_marshal_value_peek_float
+g_marshal_value_peek_double
+g_marshal_value_peek_string
+g_marshal_value_peek_param
+g_marshal_value_peek_boxed
+g_marshal_value_peek_pointer
+g_marshal_value_peek_object
+dbus_glib_marshal_parole_media_list_BOOLEAN__BOXED_POINTER
+</SECTION>
+
+<SECTION>
+<FILE>parole-utils</FILE>
+parole_window_busy_cursor
+parole_window_invisible_cursor
+thunar_file_compare_by_name
+parole_get_name_without_extension
+parole_get_subtitle_path
+</SECTION>
+
+<SECTION>
+<FILE>parole</FILE>
+parole_plugin_constructor
+ParolePluginConstruct
+PAROLE_PLUGIN_CONSTRUCT
+</SECTION>
+
+<SECTION>
+<FILE>gmarshal</FILE>
+</SECTION>
+
+<SECTION>
+<FILE>stamp-enum-gtypes</FILE>
+</SECTION>
+
+<SECTION>
+<FILE>parole-filters</FILE>
+parole_get_supported_audio_filter
+parole_get_supported_video_filter
+parole_get_supported_media_filter
+parole_file_filter
+parole_get_media_files
+</SECTION>
+
+<SECTION>
+<FILE>parole-vis</FILE>
+parole_vis_get_plugins
+</SECTION>
+
+<SECTION>
+<FILE>parole-debug</FILE>
+PAROLE_DEBUG_ENUM
+PAROLE_DEBUG_ENUM_FULL
+parole_debug_enum
+parole_debug_enum_full
+</SECTION>
+
+<SECTION>
+<FILE>parole-dbus</FILE>
+PAROLE_DBUS_NAME
+PAROLE_DBUS_PATH
+PAROLE_DBUS_INTERFACE
+parole_g_session_bus_get
+parole_dbus_name_has_owner
+parole_dbus_register_name
+parole_dbus_release_name
+</SECTION>
+

Added: parole/trunk/docs/plugin-api/Parole-Plugins.types
===================================================================
--- parole/trunk/docs/plugin-api/Parole-Plugins.types	                        (rev 0)
+++ parole/trunk/docs/plugin-api/Parole-Plugins.types	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,17 @@
+parole_plugin_get_type
+parole_media_state_get_type
+parole_plugin_container_get_type
+parole_state_get_type
+parole_media_chooser_get_type
+parole_plugins_manager_get_type
+parole_module_get_type
+parole_screen_saver_get_type
+parole_sidebar_get_type
+parole_gst_get_type
+parole_media_file_get_type
+parole_player_get_type
+parole_media_list_get_type
+parole_conf_dialog_get_type
+parole_statusbar_get_type
+parole_conf_get_type
+parole_stream_get_type

Added: parole/trunk/docs/plugin-api/version.xml.in
===================================================================
--- parole/trunk/docs/plugin-api/version.xml.in	                        (rev 0)
+++ parole/trunk/docs/plugin-api/version.xml.in	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1 @@
+ at VERSION@

Added: parole/trunk/parole/Makefile.am
===================================================================
--- parole/trunk/parole/Makefile.am	                        (rev 0)
+++ parole/trunk/parole/Makefile.am	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,181 @@
+bin_PROGRAMS = parole-media-player
+
+noinst_LTLIBRARIES =                    	\
+        libparole.la
+
+INCLUDES =					\
+	-I$(top_srcdir)				\
+	-I$(top_srcdir)/common			\
+	-I$(top_srcdir)/data			\
+	-I$(top_srcdir)/data/mime		\
+	-DLOCALEDIR=\"$(localedir)\"		\
+	-DG_LOG_DOMAIN=\"parole\"		\
+	-DPAROLE_PLUGINS_DIR=\"$(libdir)/parole-$(PAROLE_VERSION_API)\"\
+	$(GTK_CFLAGS)                           \
+        $(GLIB_CFLAGS)                          \
+        $(GOBJECT_CFLAGS)                       \
+        $(GTHREAD_CFLAGS)                       \
+	$(GIO_CFLAGS)				\
+        $(DBUS_CFLAGS)                          \
+        $(DBUS_GLIB_CFLAGS)                     \
+        $(LIBXFCE4GUI_CFLAGS)                   \
+        $(LIBXFCE4UTIL_CFLAGS)			\
+	$(GST_CFLAGS)				\
+	$(GST_BASE_CFLAGS)			\
+	$(GST_INTERFACES_CFLAGS)
+
+PAROLE_LDFLAGS =				\
+	-export-dynamic 			\
+	-no-undefined				\
+	-export-symbols-regex "^[[^_]].*"
+
+PAROLE_LIBS = 					\
+	$(top_srcdir)/common/libparolecommon.la \
+	$(GTK_LIBS)                             \
+        $(GLIB_LIBS)                            \
+        $(GOBJECT_LIBS)                         \
+        $(GTHREAD_LIBS)                         \
+	$(GIO_LIBS)				\
+        $(DBUS_LIBS)                            \
+        $(DBUS_GLIB_LIBS)                       \
+        $(LIBXFCE4GUI_LIBS)                     \
+        $(LIBXFCE4UTIL_LIBS)			\
+	$(GST_LIBS)				\
+	$(GST_BASE_LIBS)			\
+	$(GST_INTERFACES_LIBS)
+
+GENERATED_FILES =				\
+	gmarshal.c				\
+	gmarshal.h				\
+	enum-gtypes.c				\
+	enum-gtypes.h				\
+	org.parole.media.list.h
+
+INST_HFILES =					\
+	parole.h				\
+	parole-plugin.h				\
+	parole-mediafile.h			\
+	parole-stream.h
+
+NOINST_HFILES =					\
+	parole-player.h				\
+	parole-gst.h				\
+	parole-vis.h				\
+	parole-statusbar.h			\
+	parole-sidebar.h			\
+	parole-mediachooser.h			\
+	parole-filters.h			\
+	parole-screensaver.h			\
+	parole-conf.h				\
+	parole-conf-dialog.h			\
+	parole-rc-utils.h			\
+	parole-utils.h				\
+	parole-dbus.h				\
+	parole-medialist.h			\
+	parole-debug.h				\
+	parole-plugins-manager.h		\
+	parole-module.h
+
+libparole_headers =				\
+	$(INST_HFILES)
+
+libparole_includedir =				\
+	$(includedir)/parole
+
+libparole_include_HEADERS =			\
+	$(libparole_headers)
+
+libparole_la_SOURCES =				\
+	$(GENERATED_FILES)			\
+	$(INST_HFILES)				\
+	$(NOINST_HFILES)			\
+	parole-player.c				\
+	parole-gst.c				\
+	parole-stream.c				\
+	parole-mediafile.c			\
+	parole-vis.c				\
+	parole-sidebar.c			\
+	parole-statusbar.c			\
+	parole-medialist.c			\
+	parole-mediachooser.c			\
+	parole-filters.c			\
+	parole-screensaver.c			\
+	parole-conf.c				\
+	parole-conf-dialog.c			\
+	parole-rc-utils.c			\
+	parole-utils.c				\
+	parole-dbus.c				\
+	parole-debug.c				\
+	parole-plugins-manager.c		\
+	parole-plugin.c				\
+	parole-module.c
+
+libparole_la_LDFLAGS =				\
+	$(PAROLE_LDFLAGS)
+
+libparole_la_LIBADD =				\
+	$(PAROLE_LIBS)
+
+parole_media_player_SOURCES =			\
+	main.c
+
+parole_media_player_LDADD =			\
+	libparole.la				\
+	$(PAROLE_LIBS)
+
+parole_media_player_LDFLAGS =			\
+	$(PAROLE_LDFLAGS)
+
+parole_glib_enum_headers =			\
+	parole-gst.h				\
+	parole-plugin.h
+
+if MAINTAINER_MODE
+
+BUILT_SOURCES = 				\
+	$(GENERATED_FILES)
+
+gmarshal.c: gmarshal.list
+	echo "#include \"gmarshal.h\"" > $@ && \
+	glib-genmarshal $< --prefix=_gmarshal --body >> $@
+
+gmarshal.h: gmarshal.list
+	glib-genmarshal $< --prefix=_gmarshal --header > $@
+
+enum-gtypes.h: stamp-enum-gtypes.h
+	@true
+stamp-enum-gtypes.h: $(parole_glib_enum_headers) Makefile
+	( cd $(srcdir) && glib-mkenums \
+		--fhead "#ifndef __ENUM_GTYPES_H__\n#define __ENUM_GTYPES_H__\n#include <glib-object.h>\nG_BEGIN_DECLS\n" \
+		--fprod "/* enumerations from \"@filename@\" */\n" \
+		--vhead "GType @enum_name at _get_type (void);\n#define ENUM_GTYPE_ at ENUMSHORT@ (@enum_name at _get_type())\n" \
+		--ftail "G_END_DECLS\n\n#endif /* __ENUM_GTYPES_H__ */" \
+		$(parole_glib_enum_headers) ) > xgen-enum \
+	&& (cmp -s xgen-enum enum-gtypes.h || cp xgen-enum enum-gtypes.h) \
+	&& rm -f xgen-enum \
+	&& echo timestamp > $(@F)
+
+enum-gtypes.c: $(parole_glib_enum_headers) Makefile
+	( cd $(srcdir) && glib-mkenums \
+		--fhead "#include \"enum-gtypes.h\"\n\n" \
+		--fhead "#include \"parole-gst.h\"\n\n" \
+		--fhead "#include \"parole-plugin.h\"\n\n" \
+		--fprod "\n/* enumerations from \"@filename@\" */" \
+		--vhead "GType\n at enum_name@_get_type (void)\n{\n  static GType etype = 0;\n  if (etype == 0) {\n    static const G at Type@Value values[] = {" \
+		--vprod "      { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+		--vtail "      { 0, NULL, NULL }\n    };\n    etype = g_ at type@_register_static (\"@EnumName@\", values);\n  }\n  return etype;\n}\n" \
+		$(parole_glib_enum_headers) ) >> xgen-enum \
+	&& cp xgen-enum enum-gtypes.c \
+	&& rm -f xgen-enum
+
+org.parole.media.list.h: $(srcdir)/org.parole.media.list.xml
+	dbus-binding-tool --mode=glib-server --prefix=parole_media_list $< >$@
+
+endif
+
+EXTRA_DIST =					\
+	gmarshal.list
+
+DISTCLEANFILES =				\
+	$(BUILT_SOURCES)			\
+	stamp-enum-gtypes.h

Added: parole/trunk/parole/gmarshal.list
===================================================================
--- parole/trunk/parole/gmarshal.list	                        (rev 0)
+++ parole/trunk/parole/gmarshal.list	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,3 @@
+VOID:OBJECT,ENUM
+VOID:OBJECT,DOUBLE
+VOID:OBJECT,INT

Added: parole/trunk/parole/main.c
===================================================================
--- parole/trunk/parole/main.c	                        (rev 0)
+++ parole/trunk/parole/main.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,163 @@
+/*
+ * * Copyright (C) 2008-2009 Ali <aliov at 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 <unistd.h>
+#include <signal.h>
+
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <gst/gst.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "parole-player.h"
+#include "parole-plugins-manager.h"
+#include "parole-utils.h"
+#include "parole-dbus.h"
+#include "parole-builder.h"
+
+static void
+parole_send_files (gchar **filenames)
+{
+    GFile *file;
+    DBusGConnection *bus;
+    DBusGProxy *proxy;
+    gchar **out_paths;
+    GError *error = NULL;
+    guint i;
+    
+    bus = parole_g_session_bus_get ();
+    
+    out_paths = g_new (gchar *, g_strv_length (filenames));
+    
+    for ( i = 0; filenames && filenames[i]; i++)
+    {
+	file = g_file_new_for_commandline_arg (filenames[i]);
+	out_paths[i] = g_file_get_path (file);
+	g_object_unref (file);
+    }
+    
+    proxy = dbus_g_proxy_new_for_name (bus, 
+				       PAROLE_DBUS_NAME,
+				       PAROLE_DBUS_PATH,
+				       PAROLE_DBUS_INTERFACE);
+				       
+    dbus_g_proxy_call (proxy, "AddFiles", &error,
+		       G_TYPE_STRV, out_paths,
+		       G_TYPE_INVALID,
+		       G_TYPE_INVALID);
+		       
+    if ( error )
+    {
+	g_critical ("Unable to send media files to Parole: %s", error->message);
+	g_error_free (error);
+    }
+    
+    g_object_unref (proxy);
+    dbus_g_connection_unref (bus);
+    g_strfreev (out_paths);
+}
+
+int main (int argc, char **argv)
+{
+    ParolePlayer *player;
+    ParolePluginsManager *plugins;
+    GtkBuilder *builder;
+    
+    GError *error = NULL;
+    gchar **filenames = NULL;
+    gboolean new_instance = FALSE;
+    
+    GOptionEntry option_entries[] = 
+    {
+	{"new-instance", 'i', G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_NONE, &new_instance, N_("Open a new instance"), NULL },
+	{G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, N_("Media to play"), NULL},
+        { NULL, },
+    };
+    
+    if ( !g_thread_supported () )
+	g_thread_init (NULL);
+
+    xfce_textdomain (GETTEXT_PACKAGE, LOCALEDIR, "UTF-8");
+    
+    gst_init (&argc, &argv);
+    
+    if ( !gtk_init_with_args (&argc, &argv, (gchar *)"", option_entries, (gchar *)PACKAGE, &error))
+    {
+	if (G_LIKELY (error) ) 
+        {
+            g_printerr ("%s: %s.\n", G_LOG_DOMAIN, error->message);
+            g_printerr (_("Type '%s --help' for usage."), G_LOG_DOMAIN);
+            g_printerr ("\n");
+            g_error_free (error);
+        }
+        else
+        {
+            g_error ("Unable to open display.");
+        }
+
+        return EXIT_FAILURE;
+    }
+
+    if ( parole_dbus_name_has_owner (PAROLE_DBUS_NAME) )
+    {
+	TRACE ("Parole is already running");
+	if ( filenames && filenames[0] != NULL )
+	    parole_send_files (filenames);
+    }
+    else
+    {
+	builder = parole_builder_get_main_interface ();
+	parole_dbus_register_name (PAROLE_DBUS_NAME);
+	player = parole_player_new ();
+
+	if ( filenames && filenames[0] != NULL )
+	{
+	    ParoleMediaList *list;
+	    list = parole_player_get_media_list (player);
+	    parole_media_list_add_files (list, filenames);
+	}
+	plugins = parole_plugins_manager_new ();
+	parole_plugins_manager_load_plugins (plugins);
+	g_object_unref (builder);
+	
+	gdk_notify_startup_complete ();
+	gtk_main ();
+	
+	parole_dbus_release_name (PAROLE_DBUS_NAME);
+	g_object_unref (plugins);
+    }
+
+    gst_deinit ();
+    return 0;
+}

Added: parole/trunk/parole/org.parole.media.list.xml
===================================================================
--- parole/trunk/parole/org.parole.media.list.xml	                        (rev 0)
+++ parole/trunk/parole/org.parole.media.list.xml	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<node name="/">
+    <interface name="org.Parole.Media.Player">
+        <annotation name="org.freedesktop.DBus.GLib.CSymbol"
+                    value="parole_media_list_dbus"/>
+        <annotation name="org.freedesktop.DBus.GLib.ClientCSymbol"
+                    value="parole_media_list_dbus_client"/>
+
+    <method name="AddFiles">
+      <arg type="as" name="files" direction="in"/>
+    </method>
+
+    </interface>
+</node>

Added: parole/trunk/parole/parole-conf-dialog.c
===================================================================
--- parole/trunk/parole/parole-conf-dialog.c	                        (rev 0)
+++ parole/trunk/parole/parole-conf-dialog.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,287 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 "common/parole-builder.h"
+#include "interfaces/parole-settings_ui.h"
+
+#include "parole-conf-dialog.h"
+#include "parole-conf.h"
+#include "parole-vis.h"
+
+/*
+ * GtkBuilder Callbacks
+ */
+
+void		parole_conf_dialog_response_cb		 	(GtkDialog *dialog, 
+								 gint response_id, 
+								 ParoleConfDialog *self);
+							  
+void		parole_conf_dialog_enable_vis_changed_cb 	(GtkToggleButton *widget,
+								 ParoleConfDialog *self);
+
+void		parole_conf_dialog_vis_plugin_changed_cb 	(GtkComboBox *widget,
+								 ParoleConfDialog *self);
+
+void		parole_conf_dialog_font_set_cb		 	(GtkFontButton *button,
+								 ParoleConfDialog *self);
+
+void		parole_conf_dialog_enable_subtitle_changed_cb 	(GtkToggleButton *widget,
+							         ParoleConfDialog *self);
+							       
+/*
+ * End of GtkBuilder callbacks
+ */
+
+#define PAROLE_CONF_DIALOG_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_CONF_DIALOG, ParoleConfDialogPrivate))
+
+struct ParoleConfDialogPrivate
+{
+    ParoleConf *conf;
+    
+    GHashTable *vis_plugins;
+    
+    GtkWidget  *vis_combox;
+    GtkWidget  *toggle_vis;
+    GtkWidget  *toggle_subtitle;
+    GtkWidget  *font_button;
+};
+
+G_DEFINE_TYPE (ParoleConfDialog, parole_conf_dialog, G_TYPE_OBJECT)
+
+static void 
+parole_conf_dialog_destroy (GtkWidget *widget, ParoleConfDialog *self)
+{
+    gtk_widget_destroy (widget);
+    g_object_unref (self);
+}
+
+void parole_conf_dialog_response_cb (GtkDialog *dialog, gint response_id, ParoleConfDialog *self)
+{
+    switch (response_id)
+    {
+	case GTK_RESPONSE_HELP:
+	    break;
+	default:
+	    parole_conf_dialog_destroy (GTK_WIDGET (dialog), self);
+	    break;
+    }
+}
+
+void parole_conf_dialog_enable_vis_changed_cb (GtkToggleButton *widget, ParoleConfDialog *self)
+{
+    gboolean active;
+    
+    active = gtk_toggle_button_get_active (widget);
+    
+    g_object_set (G_OBJECT (self->priv->conf),
+		  "vis-enabled", active,
+		  NULL);
+    
+    gtk_widget_set_sensitive (self->priv->vis_combox, active);
+}
+
+void parole_conf_dialog_vis_plugin_changed_cb (GtkComboBox *widget,  ParoleConfDialog *self)
+{
+    gchar *active;
+    GstElementFactory *f;
+    
+    active = gtk_combo_box_get_active_text (widget);
+    
+    f = g_hash_table_lookup (self->priv->vis_plugins, active);
+    
+    if ( f )
+    {
+	g_object_set (G_OBJECT (self->priv->conf),
+		      "vis-name", GST_PLUGIN_FEATURE_NAME (f),
+		      NULL);
+    }
+    
+    g_free (active);
+}
+
+void parole_conf_dialog_font_set_cb (GtkFontButton *button, ParoleConfDialog *self)
+{
+    g_object_set (G_OBJECT (self->priv->conf), 
+		  "subtitle-font", gtk_font_button_get_font_name (button),
+		  NULL);
+}
+
+void parole_conf_dialog_enable_subtitle_changed_cb (GtkToggleButton *widget, ParoleConfDialog *self)
+{
+    gboolean active;
+    
+    active = gtk_toggle_button_get_active (widget);
+    
+    g_object_set (G_OBJECT (self->priv->conf),
+		  "enable-subtitle", active,
+		  NULL);
+    
+    gtk_widget_set_sensitive (self->priv->font_button, active);
+    
+}
+
+static void
+parole_conf_dialog_finalize (GObject *object)
+{
+    ParoleConfDialog *self;
+
+    self = PAROLE_CONF_DIALOG (object);
+    
+    g_object_unref (self->priv->conf);
+    g_hash_table_destroy (self->priv->vis_plugins);
+
+    G_OBJECT_CLASS (parole_conf_dialog_parent_class)->finalize (object);
+}
+
+static void
+parole_conf_dialog_class_init (ParoleConfDialogClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_conf_dialog_finalize;
+
+    g_type_class_add_private (klass, sizeof (ParoleConfDialogPrivate));
+}
+
+static void
+parole_conf_dialog_init (ParoleConfDialog *self)
+{
+    self->priv = PAROLE_CONF_DIALOG_GET_PRIVATE (self);
+    self->priv->conf = parole_conf_new ();
+    
+    self->priv->vis_plugins = parole_vis_get_plugins ();
+}
+
+static void
+parole_conf_dialog_add_vis_plugins (gpointer key, gpointer value, GtkWidget *combox)
+{
+    gtk_combo_box_append_text (GTK_COMBO_BOX (combox), (const gchar *) key);
+}
+
+static gboolean 
+parole_conf_dialog_set_default_vis_plugin (GtkTreeModel *model, GtkTreePath *path,
+					   GtkTreeIter *iter, ParoleConfDialog *self)
+{
+    GstElementFactory *f;
+    gchar *vis_name;
+    gchar *combox_text;
+    gboolean ret = FALSE;
+    
+    g_object_get (G_OBJECT (self->priv->conf),
+		  "vis-name", &vis_name,
+		  NULL);
+
+    gtk_tree_model_get (model, iter, 
+			0, &combox_text,
+			-1);
+
+    f = g_hash_table_lookup (self->priv->vis_plugins, combox_text);
+    
+    if ( !g_strcmp0 (vis_name, "none") )
+    {
+	if ( !g_strcmp0 (GST_PLUGIN_FEATURE_NAME (f), "Goom") )
+	    ret = TRUE;
+    }
+    else if ( !g_strcmp0 (GST_PLUGIN_FEATURE_NAME (f), vis_name) )
+    {
+	ret = TRUE;
+    }
+    
+    if ( ret == TRUE )
+	gtk_combo_box_set_active_iter (GTK_COMBO_BOX (self->priv->vis_combox), iter);
+    
+    return ret;
+}
+
+static void
+parole_conf_dialog_set_defaults (ParoleConfDialog *self)
+{
+    GtkTreeModel *model;
+    gboolean vis_enabled;
+    gboolean subtitle;
+    gchar *subtitle_font;
+    
+    g_object_get (G_OBJECT (self->priv->conf),
+		  "vis-enabled", &vis_enabled,
+		  "enable-subtitle", &subtitle,
+		  "subtitle-font", &subtitle_font,
+		  NULL);
+
+    gtk_widget_set_sensitive (self->priv->vis_combox, vis_enabled);
+    gtk_widget_set_sensitive (self->priv->font_button, subtitle);
+    
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->toggle_vis), vis_enabled);
+    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->toggle_subtitle), subtitle);
+    
+    model = gtk_combo_box_get_model (GTK_COMBO_BOX (self->priv->vis_combox));
+
+    gtk_tree_model_foreach (model, 
+			    (GtkTreeModelForeachFunc) parole_conf_dialog_set_default_vis_plugin,
+			    self);
+			    
+    gtk_font_button_set_font_name (GTK_FONT_BUTTON (self->priv->font_button), subtitle_font);
+    g_free (subtitle_font);
+}
+
+ParoleConfDialog *
+parole_conf_dialog_new (void)
+{
+    ParoleConfDialog *parole_conf_dialog = NULL;
+    parole_conf_dialog = g_object_new (PAROLE_TYPE_CONF_DIALOG, NULL);
+    return parole_conf_dialog;
+}
+
+void parole_conf_dialog_open (ParoleConfDialog *self, GtkWidget *parent)
+{
+    GtkBuilder *builder;
+    GtkWidget  *dialog;
+    GtkWidget  *combox;
+    
+    builder = parole_builder_new_from_string (parole_settings_ui, parole_settings_ui_length);
+    
+    dialog = GTK_WIDGET (gtk_builder_get_object (builder, "settings-dialog"));
+    combox = GTK_WIDGET (gtk_builder_get_object (builder, "vis-combobox"));
+    
+    self->priv->toggle_vis = GTK_WIDGET (gtk_builder_get_object (builder, "enable-vis"));
+    self->priv->toggle_subtitle = GTK_WIDGET (gtk_builder_get_object (builder, "enable-subtitle"));
+    self->priv->font_button = GTK_WIDGET (gtk_builder_get_object (builder, "fontbutton"));
+    
+    g_hash_table_foreach (self->priv->vis_plugins, (GHFunc) parole_conf_dialog_add_vis_plugins, combox);
+    
+    gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
+    
+    self->priv->vis_combox = combox;
+
+    parole_conf_dialog_set_defaults (self);
+    
+    gtk_builder_connect_signals (builder, self);
+    
+    g_object_unref (builder);
+    gtk_widget_show_all (dialog);
+}

Added: parole/trunk/parole/parole-conf-dialog.h
===================================================================
--- parole/trunk/parole/parole-conf-dialog.h	                        (rev 0)
+++ parole/trunk/parole/parole-conf-dialog.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,56 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_CONF_DIALOG_H
+#define __PAROLE_CONF_DIALOG_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_CONF_DIALOG        (parole_conf_dialog_get_type () )
+#define PAROLE_CONF_DIALOG(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_CONF_DIALOG, ParoleConfDialog))
+#define PAROLE_IS_CONF_DIALOG(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_CONF_DIALOG))
+
+typedef struct ParoleConfDialogPrivate ParoleConfDialogPrivate;
+
+typedef struct
+{
+    GObject         		 parent;
+    ParoleConfDialogPrivate     *priv;
+    
+} ParoleConfDialog;
+
+typedef struct
+{
+    GObjectClass 		 parent_class;
+    
+} ParoleConfDialogClass;
+
+GType        			 parole_conf_dialog_get_type        (void) G_GNUC_CONST;
+ParoleConfDialog       		*parole_conf_dialog_new             (void);
+
+void				 parole_conf_dialog_open	    (ParoleConfDialog *self,
+								     GtkWidget *parent);
+
+G_END_DECLS
+
+#endif /* __PAROLE_CONF_DIALOG_H */

Added: parole/trunk/parole/parole-conf.c
===================================================================
--- parole/trunk/parole/parole-conf.c	                        (rev 0)
+++ parole/trunk/parole/parole-conf.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,205 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <glib.h>
+
+#include "parole-conf.h"
+#include "parole-rc-utils.h"
+
+#define PAROLE_CONF_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_CONF, ParoleConfPrivate))
+
+struct ParoleConfPrivate
+{
+    gchar 	*vis_sink;
+    gboolean 	 enable_vis;
+    gboolean	 enable_subtitle;
+    gchar	*subtitle_font;
+};
+
+static gpointer parole_conf_object = NULL;
+
+G_DEFINE_TYPE (ParoleConf, parole_conf, G_TYPE_OBJECT)
+
+enum
+{
+    PROP_0,
+    PROP_VIS_ENABLED,
+    PROP_VIS_NAME,
+    PROP_SUBTITLE_ENABLED,
+    PROP_SUBTITLE_FONT,
+};
+
+static void parole_conf_set_property (GObject *object,
+				      guint prop_id,
+				      const GValue *value,
+				      GParamSpec *pspec)
+{
+    ParoleConf *conf;
+    conf = PAROLE_CONF (object);
+
+    switch (prop_id)
+    {
+	case PROP_VIS_ENABLED:
+	    conf->priv->enable_vis = g_value_get_boolean (value);
+	    g_object_notify (G_OBJECT (conf), "vis-enabled");
+	    parole_rc_write_entry_bool ("VIS_ENABLED", conf->priv->enable_vis);
+	    break;
+	case PROP_VIS_NAME:
+	    if ( conf->priv->vis_sink )
+		g_free (conf->priv->vis_sink);
+	    conf->priv->vis_sink = g_strdup (g_value_get_string (value));
+	    g_object_notify (G_OBJECT (conf), "vis-name");
+	    parole_rc_write_entry_string ("VIS_NAME", conf->priv->vis_sink);
+	    break;
+	case PROP_SUBTITLE_ENABLED:
+	    conf->priv->enable_subtitle = g_value_get_boolean (value);
+	    g_object_notify (G_OBJECT (conf), "enable-subtitle");
+	    parole_rc_write_entry_bool ("ENABLE_SUBTITLE", conf->priv->enable_subtitle);
+	    break;
+	case PROP_SUBTITLE_FONT:
+	    if ( conf->priv->subtitle_font )
+		g_free (conf->priv->subtitle_font);
+	    conf->priv->subtitle_font = g_strdup (g_value_get_string (value));
+	    g_object_notify (G_OBJECT (conf), "subtitle-font");
+	    parole_rc_write_entry_string ("SUBTITLE_FONT", conf->priv->subtitle_font);
+	    break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void parole_conf_get_property (GObject *object,
+				      guint prop_id,
+				      GValue *value,
+				      GParamSpec *pspec)
+{
+    ParoleConf *conf;
+    conf = PAROLE_CONF (object);
+
+    switch (prop_id)
+    {
+	case PROP_VIS_ENABLED:
+	    g_value_set_boolean (value, conf->priv->enable_vis);
+	    break;
+	case PROP_VIS_NAME:
+	    g_value_set_string (value, conf->priv->vis_sink);
+	    break;
+	case PROP_SUBTITLE_ENABLED:
+	    g_value_set_boolean (value, conf->priv->enable_subtitle);
+	    break;
+	case PROP_SUBTITLE_FONT:
+	    g_value_set_string (value, conf->priv->subtitle_font);
+	    break;
+	default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+parole_conf_finalize (GObject *object)
+{
+    ParoleConf *conf;
+
+    conf = PAROLE_CONF (object);
+    
+    g_free (conf->priv->vis_sink);
+    g_free (conf->priv->subtitle_font);
+
+    G_OBJECT_CLASS (parole_conf_parent_class)->finalize (object);
+}
+
+static void
+parole_conf_class_init (ParoleConfClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_conf_finalize;
+
+    object_class->get_property = parole_conf_get_property;
+    object_class->set_property = parole_conf_set_property;
+
+    g_object_class_install_property (object_class,
+                                     PROP_VIS_ENABLED,
+                                     g_param_spec_boolean ("vis-enabled",
+                                                           NULL, NULL,
+                                                           FALSE,
+                                                           G_PARAM_READWRITE));
+
+    g_object_class_install_property (object_class,
+                                     PROP_VIS_NAME,
+                                     g_param_spec_string  ("vis-name",
+                                                           NULL, NULL,
+                                                           NULL,
+                                                           G_PARAM_READWRITE));
+
+    g_object_class_install_property (object_class,
+                                     PROP_SUBTITLE_ENABLED,
+                                     g_param_spec_boolean ("enable-subtitle",
+                                                           NULL, NULL,
+                                                           FALSE,
+                                                           G_PARAM_READWRITE));
+							   
+    g_object_class_install_property (object_class,
+                                     PROP_SUBTITLE_FONT,
+                                     g_param_spec_string  ("subtitle-font",
+                                                           NULL, NULL,
+                                                           NULL,
+                                                           G_PARAM_READWRITE));
+    
+    g_type_class_add_private (klass, sizeof (ParoleConfPrivate));
+}
+
+static void
+parole_conf_init (ParoleConf *conf)
+{
+    conf->priv = PAROLE_CONF_GET_PRIVATE (conf);
+    
+    conf->priv->enable_vis = parole_rc_read_entry_bool ("VIS_ENABLED", FALSE);
+    conf->priv->vis_sink   = g_strdup (parole_rc_read_entry_string ("VIS_NAME", "none"));
+    conf->priv->enable_subtitle = parole_rc_read_entry_bool ("ENABLE_SUBTITLE", TRUE);
+    conf->priv->subtitle_font = g_strdup (parole_rc_read_entry_string ("SUBTITLE_FONT", "Sans 12"));
+}
+
+ParoleConf *
+parole_conf_new (void)
+{
+    if ( parole_conf_object != NULL )
+    {
+	g_object_ref (parole_conf_object);
+    }
+    else
+    {
+	parole_conf_object = g_object_new (PAROLE_TYPE_CONF, NULL);
+	g_object_add_weak_pointer (parole_conf_object, &parole_conf_object);
+    }
+
+    return PAROLE_CONF (parole_conf_object);
+}

Added: parole/trunk/parole/parole-conf.h
===================================================================
--- parole/trunk/parole/parole-conf.h	                        (rev 0)
+++ parole/trunk/parole/parole-conf.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,52 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_CONF_H
+#define __PAROLE_CONF_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_CONF        (parole_conf_get_type () )
+#define PAROLE_CONF(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_CONF, ParoleConf))
+#define PAROLE_IS_CONF(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_CONF))
+
+typedef struct ParoleConfPrivate ParoleConfPrivate;
+
+typedef struct
+{
+    GObject         		 parent;
+    ParoleConfPrivate     	*priv;
+    
+} ParoleConf;
+
+typedef struct
+{
+    GObjectClass 		 parent_class;
+    
+} ParoleConfClass;
+
+GType        			 parole_conf_get_type        (void) G_GNUC_CONST;
+ParoleConf       		*parole_conf_new             (void);
+
+G_END_DECLS
+
+#endif /* __PAROLE_CONF_H */

Added: parole/trunk/parole/parole-dbus.c
===================================================================
--- parole/trunk/parole/parole-dbus.c	                        (rev 0)
+++ parole/trunk/parole/parole-dbus.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,121 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <glib.h>
+
+#include "parole-dbus.h"
+
+static DBusConnection *
+parole_session_bus_get (void)
+{
+    return dbus_g_connection_get_connection (parole_g_session_bus_get ());
+}
+
+DBusGConnection *
+parole_g_session_bus_get	(void)
+{
+    static DBusGConnection *bus = NULL;
+    GError *error = NULL;
+    
+    if ( bus == NULL )
+    {
+	bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+    
+	if ( error )
+	{
+	    g_error ("%s", error->message);
+	}
+    }
+    return bus;
+}
+
+gboolean	parole_dbus_name_has_owner		(const gchar *name)
+{
+    DBusError error;
+    gboolean ret;
+    
+    dbus_error_init (&error);
+    
+    ret = dbus_bus_name_has_owner (parole_session_bus_get (), name, &error);
+    
+    if ( dbus_error_is_set (&error) )
+    {
+        g_warning ("Failed to get name owner: %s\n", error.message);
+        dbus_error_free (&error);
+    }
+    
+    return ret;
+}
+
+gboolean	parole_dbus_register_name		(const gchar *name)
+{
+    DBusError error;
+    int ret;
+    
+    dbus_error_init (&error);
+    
+    ret =
+        dbus_bus_request_name (parole_session_bus_get (),
+                               name,
+                               DBUS_NAME_FLAG_DO_NOT_QUEUE,
+                               &error);
+        
+    if ( dbus_error_is_set (&error) )
+    {
+        g_warning ("Error: %s\n", error.message);
+        dbus_error_free (&error);
+        return FALSE;
+    }
+
+    return ret == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ? TRUE : FALSE;
+}
+
+gboolean	parole_dbus_release_name		(const gchar *name)
+{
+    DBusError error;
+    int ret;
+    
+    dbus_error_init (&error);
+    
+    ret =
+        dbus_bus_release_name (parole_session_bus_get (),
+                               name,
+                               &error);
+    
+    if ( dbus_error_is_set (&error) )
+    {
+        g_warning ("Error: %s\n", error.message);
+        dbus_error_free (&error);
+        return FALSE;
+    }
+
+    return ret == -1 ? FALSE : TRUE;
+}

Added: parole/trunk/parole/parole-dbus.h
===================================================================
--- parole/trunk/parole/parole-dbus.h	                        (rev 0)
+++ parole/trunk/parole/parole-dbus.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,38 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_DBUS_H_
+#define __PAROLE_DBUS_H_
+
+#include <dbus/dbus-glib.h>
+
+#define PAROLE_DBUS_NAME	"org.Parole.Media.Player"
+#define PAROLE_DBUS_PATH	"/org/Parole/Media/Player"
+#define PAROLE_DBUS_INTERFACE	"org.Parole.Media.Player"
+
+DBusGConnection 	*parole_g_session_bus_get		(void);
+
+gboolean		 parole_dbus_name_has_owner		(const gchar *name);
+
+gboolean		 parole_dbus_register_name		(const gchar *name);
+
+gboolean		 parole_dbus_release_name		(const gchar *name);
+
+#endif /* __PAROLE_DBUS_ */

Added: parole/trunk/parole/parole-debug.c
===================================================================
--- parole/trunk/parole/parole-debug.c	                        (rev 0)
+++ parole/trunk/parole/parole-debug.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,81 @@
+/*
+ * * Copyright (C) 2008-2009 Ali <aliov at 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 <glib.h>
+#include <glib-object.h>
+#include <glib/gprintf.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "parole-debug.h"
+
+#if defined(DEBUG) && defined(G_HAVE_ISO_VARARGS)
+
+void parole_debug_enum (const gchar *func, const gchar *file, gint line, 
+		        const gchar *text, gint v_enum, GType type)
+{
+    gchar *content = NULL;
+    GValue __value__ = { 0, };
+
+    g_value_init (&__value__, type);
+    g_value_set_enum (&__value__, v_enum);
+    
+    content = g_strdup_value_contents (&__value__);
+    
+    fprintf(stdout, "TRACE[%s:%d] %s(): %s : %s", file, line , func, text, content);
+    fprintf(stdout, "\n");
+    
+    g_value_unset (&__value__);						
+    g_free (content);
+}
+
+void parole_debug_enum_full (const gchar *func, const gchar *file, gint line,
+			     gint v_enum, GType type, const gchar *format, ...)
+{
+    va_list args;
+    gchar *buffer;
+    
+    gchar *content = NULL;
+    GValue __value__ = { 0, };
+    
+    g_value_init (&__value__, type);
+    g_value_set_enum (&__value__, v_enum);
+    
+    content = g_strdup_value_contents (&__value__);
+    
+    va_start (args, format);
+    g_vasprintf (&buffer, format, args);
+    va_end (args);
+	
+    fprintf(stdout, "TRACE[%s:%d] %s(): ", file, line, func);
+    fprintf(stdout, "%s: %s", buffer, content);
+    fprintf(stdout, "\n");
+    
+    g_value_unset (&__value__);	
+    g_free (content);
+    g_free (buffer);
+}
+
+#endif /*#if defined(DEBUG) && defined(G_HAVE_ISO_VARARGS)*/

Added: parole/trunk/parole/parole-debug.h
===================================================================
--- parole/trunk/parole/parole-debug.h	                        (rev 0)
+++ parole/trunk/parole/parole-debug.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,66 @@
+/*
+ * * Copyright (C) 2008-2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_DEBUG_H
+#define __PAROLE_DEBUG_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#if defined(DEBUG) && defined(G_HAVE_ISO_VARARGS)
+
+#define PAROLE_DEBUG_ENUM(_text, _value, _type)\
+    parole_debug_enum (__func__, __FILE__, __LINE__, _text, _value, _type)
+
+#define PAROLE_DEBUG_ENUM_FULL(_value, _type, ...)\
+    parole_debug_enum_full (__func__, __FILE__, __LINE__, _value, _type, __VA_ARGS__)
+
+void		parole_debug_enum 	(const gchar *func,
+					 const gchar *file,
+					 gint line,
+					 const gchar *text,
+					 gint v_enum, 
+					 GType type);
+					 
+void		parole_debug_enum_full   (const gchar *func,
+					 const gchar *file,
+					 gint line,
+					 gint v_enum,
+					 GType type,
+					 const gchar *format,
+					 ...) G_GNUC_PRINTF (6, 7);
+
+
+#else
+
+#define PAROLE_DEBUG_ENUM(_text, _value, _type)
+#define PAROLE_DEBUG_ENUM_FULL(_value, _type, ...)
+
+#endif
+
+G_END_DECLS
+
+#endif /* __XFPM_DEBUG_H */

Added: parole/trunk/parole/parole-filters.c
===================================================================
--- parole/trunk/parole/parole-filters.c	                        (rev 0)
+++ parole/trunk/parole/parole-filters.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,152 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <libxfce4util/libxfce4util.h>
+#include <glib.h>
+
+#include "parole-filters.h"
+#include "parole-utils.h"
+#include "data/mime/parole-mime-types.h"
+
+/*
+ * Supported Audio formats.
+ */
+GtkFileFilter 		*parole_get_supported_audio_filter	(void)
+{
+    GtkFileFilter *filter;
+    guint i;
+    
+    filter = gtk_file_filter_new ();
+    
+    gtk_file_filter_set_name (filter, _("Audio"));
+    
+    for ( i = 0; i < G_N_ELEMENTS (audio_mime_types); i++)
+	gtk_file_filter_add_mime_type (filter, audio_mime_types[i]);
+    
+    return filter;
+}
+
+/*
+ * Supported Video formats.
+ */
+GtkFileFilter 		*parole_get_supported_video_filter	(void)
+{
+    GtkFileFilter *filter;
+    guint i;
+    
+    filter = gtk_file_filter_new ();
+    
+    gtk_file_filter_set_name (filter, _("Video"));
+    
+    for ( i = 0; i < G_N_ELEMENTS (video_mime_types); i++)
+	gtk_file_filter_add_mime_type (filter, video_mime_types[i]);
+    
+    return filter;
+}
+
+/*
+ * Supported Audio And Video.
+ */
+GtkFileFilter 		*parole_get_supported_media_filter	(void)
+{
+    GtkFileFilter *filter;
+    guint i;
+    
+    filter = gtk_file_filter_new ();
+    
+    gtk_file_filter_set_name (filter, _("Audio and video"));
+    
+    for ( i = 0; i < G_N_ELEMENTS (audio_mime_types); i++)
+	gtk_file_filter_add_mime_type (filter, audio_mime_types[i]);
+	
+    for ( i = 0; i < G_N_ELEMENTS (video_mime_types); i++)
+	gtk_file_filter_add_mime_type (filter, video_mime_types[i]);
+    
+    return filter;
+}
+
+gboolean parole_file_filter (GtkFileFilter *filter, ParoleMediaFile *file)
+{
+    GtkFileFilterInfo filter_info;
+
+    gboolean ret;
+    
+    filter_info.display_name = parole_media_file_get_display_name (file);
+    filter_info.mime_type = parole_media_file_get_content_type (file);
+    
+    filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE;
+    
+    ret = gtk_file_filter_filter (filter, &filter_info);
+
+    return ret;
+}
+
+void parole_get_media_files (GtkFileFilter *filter, const gchar *path, GSList **list)
+{
+    GSList *list_internal = NULL;
+    GDir *dir;
+    const gchar *name;
+    ParoleMediaFile *file;
+
+    if ( g_file_test (path, G_FILE_TEST_IS_REGULAR ) )
+    {
+	file = parole_media_file_new (path);
+	if ( parole_file_filter (filter, file) )
+	    *list = g_slist_append (*list, file);
+	else
+	    g_object_unref (file);
+    }
+    else if ( g_file_test (path, G_FILE_TEST_IS_DIR ) )
+    {
+	dir = g_dir_open (path, 0, NULL);
+    
+	if ( G_UNLIKELY (dir == NULL) )
+	    return;
+	
+	while ( (name = g_dir_read_name (dir)) )
+	{
+	    gchar *path_internal = g_strdup_printf ("%s/%s", path, name);
+	    if ( g_file_test (path_internal, G_FILE_TEST_IS_DIR) )
+	    {
+		parole_get_media_files (filter, path_internal, list);
+	    }
+	    else if ( g_file_test (path_internal, G_FILE_TEST_IS_REGULAR) )
+	    {
+		file = parole_media_file_new (path_internal);
+		if ( parole_file_filter (filter, file) )
+		    list_internal = g_slist_append (list_internal, file);
+		else
+		    g_object_unref (file);
+	    }
+	    g_free (path_internal);
+	}
+	list_internal = g_slist_sort (list_internal, (GCompareFunc) thunar_file_compare_by_name);
+	g_dir_close (dir);
+	*list = g_slist_concat (*list, list_internal);
+    }
+}

Added: parole/trunk/parole/parole-filters.h
===================================================================
--- parole/trunk/parole/parole-filters.h	                        (rev 0)
+++ parole/trunk/parole/parole-filters.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,40 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_FILTERS_H
+#define __PAROLE_FILTERS_H
+
+#include <gtk/gtk.h>
+#include "parole-mediafile.h"
+
+GtkFileFilter 		*parole_get_supported_audio_filter	(void);
+
+GtkFileFilter 		*parole_get_supported_video_filter	(void);
+
+GtkFileFilter 		*parole_get_supported_media_filter	(void);
+
+gboolean		 parole_file_filter			(GtkFileFilter *filter,
+								 ParoleMediaFile *file);
+
+void			 parole_get_media_files			(GtkFileFilter *filter,
+								 const gchar *path,
+								 GSList **list);
+
+#endif /* PAROLE_FILTERS_H */

Added: parole/trunk/parole/parole-gst.c
===================================================================
--- parole/trunk/parole/parole-gst.c	                        (rev 0)
+++ parole/trunk/parole/parole-gst.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,1146 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <glib.h>
+
+#include <gst/gst.h>
+#include <gst/interfaces/xoverlay.h>
+
+#include <libxfce4util/libxfce4util.h>
+#include <libxfcegui4/libxfcegui4.h>
+
+#include <gdk/gdkx.h>
+
+#include "parole-gst.h"
+#include "parole-utils.h"
+#include "parole-conf.h"
+#include "parole-utils.h"
+#include "enum-gtypes.h"
+#include "gmarshal.h"
+
+#define HIDE_WINDOW_CURSOR_TIMEOUT 3.0f
+
+#define PAROLE_GST_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_GST, ParoleGstPrivate))
+
+static void	parole_gst_play_file_internal 	(ParoleGst *gst);
+static void     parole_gst_change_state 	(ParoleGst *gst, 
+						 GstState new);
+struct ParoleGstPrivate
+{
+    GstElement	 *playbin;
+    GstElement   *video_sink;
+    GstElement   *vis_sink;
+    
+    GMutex       *lock;
+    GstState      state;
+    GstState      target;
+    
+    ParoleStream *stream;
+    gulong	  tick_id;
+    GdkPixbuf    *logo;
+    GTimer	 *hidecursor_timer;
+    
+    ParoleConf   *conf;
+    gboolean	  update;
+    gboolean      with_vis;
+};
+
+enum
+{
+    MEDIA_STATE,
+    MEDIA_PROGRESSED,
+    MEDIA_TAG,
+    BUFFERING,
+    ERROR,
+    LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (ParoleGst, parole_gst, GTK_TYPE_WIDGET)
+
+static void
+parole_gst_finalize (GObject *object)
+{
+    ParoleGst *gst;
+
+    gst = PAROLE_GST (object);
+    
+    TRACE ("start");
+    
+    if ( gst->priv->tick_id != 0)
+	g_source_remove (gst->priv->tick_id);
+	
+    parole_stream_init_properties (gst->priv->stream);
+    g_object_unref (gst->priv->stream);
+    g_object_unref (gst->priv->playbin);
+    
+    g_object_unref (gst->priv->logo);
+    g_mutex_free (gst->priv->lock);
+
+    g_object_unref (gst->priv->conf);
+
+    G_OBJECT_CLASS (parole_gst_parent_class)->finalize (object);
+}
+
+static void 
+parole_gst_set_cursor_visible (ParoleGst *gst, gboolean visible)
+{
+    if ( visible )
+    {
+	gst->priv->target == gst->priv->state ? gdk_window_set_cursor (GTK_WIDGET (gst)->window, NULL):
+						parole_window_busy_cursor (GTK_WIDGET (gst)->window);
+    }
+    else
+	parole_window_invisible_cursor (GTK_WIDGET (gst)->window);
+}
+
+static void
+parole_gst_set_window_cursor (GdkWindow *window, GdkCursor *cursor)
+{
+    if ( window )
+        gdk_window_set_cursor (window, cursor);
+}
+
+static gboolean
+parole_gst_configure_event_cb (GtkWidget *widget, GdkEventConfigure *ev, ParoleGst *gst)
+{
+    
+    
+    return FALSE;
+}
+
+static void
+parole_gst_realize (GtkWidget *widget)
+{
+    ParoleGst *gst;
+    GdkWindowAttr attr;
+    GdkColor color;
+    gint mask;
+    
+    GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+    gst = PAROLE_GST (widget);
+    
+    attr.x = widget->allocation.x;
+    attr.y = widget->allocation.y;
+    attr.width = widget->allocation.width;
+    attr.height = widget->allocation.height;
+    attr.visual = gtk_widget_get_visual (widget);
+    attr.colormap = gtk_widget_get_colormap (widget);
+    attr.wclass = GDK_INPUT_OUTPUT;
+    attr.window_type = GDK_WINDOW_CHILD;
+    attr.event_mask = gtk_widget_get_events (widget) | 
+                      GDK_EXPOSURE_MASK |
+	              GDK_BUTTON_PRESS_MASK | 
+                      GDK_BUTTON_RELEASE_MASK | 
+		      GDK_POINTER_MOTION_MASK |
+		      GDK_KEY_PRESS_MASK;
+		      
+    mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+	
+    widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+				     &attr, mask);
+				     
+    gdk_window_set_user_data (widget->window, widget);
+    gdk_color_parse ("black", &color);
+    gdk_colormap_alloc_color (gtk_widget_get_colormap (widget), &color,
+			      TRUE, TRUE);
+    
+    gdk_window_set_background (widget->window, &color);
+    widget->style = gtk_style_attach (widget->style, widget->window);
+    
+    g_signal_connect (gtk_widget_get_toplevel (widget), "configure_event",
+		      G_CALLBACK (parole_gst_configure_event_cb), gst);
+}
+
+static void
+parole_gst_show (GtkWidget *widget)
+{
+    ParoleGst *gst;
+    
+    gst = PAROLE_GST (widget);
+    
+    gdk_window_show (widget->window);
+    
+    if ( GTK_WIDGET_CLASS (parole_gst_parent_class)->show )
+	GTK_WIDGET_CLASS (parole_gst_parent_class)->show (widget);
+}
+
+static void
+parole_gst_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
+{
+    g_return_if_fail (allocation != NULL);
+    
+    widget->allocation = *allocation;
+
+    if ( GTK_WIDGET_REALIZED (widget) )
+    {
+	gdk_window_move_resize (widget->window,
+                                allocation->x, allocation->y,
+                                allocation->width, allocation->height);
+				
+	gtk_widget_queue_draw (widget);
+    }
+}
+
+static void
+parole_gst_draw_logo (ParoleGst *gst)
+{
+    GdkPixbuf *pix;
+    GdkRegion *region;
+    GdkRectangle rect;
+    GtkWidget *widget;
+
+    widget = GTK_WIDGET (gst);
+
+    if ( !widget->window )
+	return;
+
+    rect.x = 0;
+    rect.y = 0;
+    
+    rect.width = widget->allocation.width;
+    rect.height = widget->allocation.height;
+
+    region = gdk_region_rectangle (&rect);
+    
+    gdk_window_begin_paint_region (widget->window,
+				   region);
+
+    gdk_window_clear_area (widget->window,
+			   0, 0,
+			   widget->allocation.width,
+			   widget->allocation.height);
+			   
+    pix = gdk_pixbuf_scale_simple (gst->priv->logo,
+				   widget->allocation.width,
+				   widget->allocation.height,
+				   GDK_INTERP_BILINEAR);
+
+    gdk_draw_pixbuf (GDK_DRAWABLE (widget->window),
+		     GTK_WIDGET(widget)->style->fg_gc[0],
+		     pix,
+		     0, 0, 0, 0,
+		     widget->allocation.width,
+		     widget->allocation.height,
+		     GDK_RGB_DITHER_NONE,
+		     0, 0);
+
+    gdk_pixbuf_unref (pix);
+    gdk_window_end_paint (GTK_WIDGET (gst)->window);
+}
+
+static void
+parole_gst_set_x_overlay (ParoleGst *gst)
+{
+    GstElement *video_sink;
+    
+    g_object_get (G_OBJECT (gst->priv->playbin),
+		  "video-sink", &video_sink,
+		  NULL);
+		  
+    g_assert (video_sink != NULL);
+    
+    gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (video_sink),
+				  GDK_WINDOW_XWINDOW (GTK_WIDGET (gst)->window));
+    
+    gst_object_unref (video_sink);
+}
+
+static gboolean
+parole_gst_expose_event (GtkWidget *widget, GdkEventExpose *ev)
+{
+    ParoleGst *gst;
+    gboolean playing_video;
+
+    if ( ev && ev->count > 0 )
+	return TRUE;
+
+    gst = PAROLE_GST (widget);
+
+    g_object_get (G_OBJECT (gst->priv->stream),
+		  "has-video", &playing_video,
+		  NULL);
+
+    parole_gst_set_x_overlay (gst);
+
+    if ( (gst->priv->state < GST_STATE_PAUSED || !gst->priv->with_vis) && !playing_video)
+	parole_gst_draw_logo (gst);
+    else 
+    {
+	TRACE ("Exposing GST");
+	gst_x_overlay_expose (GST_X_OVERLAY (gst->priv->video_sink));
+    }
+	
+    return TRUE;
+}
+
+static void
+parole_gst_load_logo (ParoleGst *gst)
+{
+    gchar *path;
+
+    path = g_strdup_printf ("%s/parole.png", PIXMAPS_DIR);
+    gst->priv->logo = gdk_pixbuf_new_from_file (path, NULL);
+    g_free (path);
+}
+
+static gboolean
+parole_gst_tick_timeout (gpointer data)
+{
+    ParoleGst *gst;
+    
+    gint64 pos;
+    GstFormat format = GST_FORMAT_TIME;
+    gdouble value;
+    
+    gst = PAROLE_GST (data);
+    
+    gst_element_query_position (gst->priv->playbin, &format, &pos);
+    
+    if ( G_UNLIKELY (format != GST_FORMAT_TIME ) )
+	goto out;
+	
+    value = ( pos / ((gdouble) 60 * 1000 * 1000 * 1000 ));
+    
+    g_signal_emit (G_OBJECT (gst), signals [MEDIA_PROGRESSED], 0, gst->priv->stream, value);
+
+out:
+    if ( g_timer_elapsed (gst->priv->hidecursor_timer, NULL ) > HIDE_WINDOW_CURSOR_TIMEOUT )
+	parole_gst_set_cursor_visible (gst, FALSE);
+	
+    return TRUE;
+}
+
+static void
+parole_gst_tick (ParoleGst *gst)
+{
+    if ( gst->priv->state >= GST_STATE_PAUSED )
+    {
+	if ( gst->priv->tick_id != 0 )
+	{
+	    return;
+	}
+	gst->priv->tick_id = g_timeout_add (1000, (GSourceFunc) parole_gst_tick_timeout, gst);
+    }
+    else if ( gst->priv->tick_id != 0)
+    {
+        g_source_remove (gst->priv->tick_id);
+	gst->priv->tick_id = 0;
+    }    
+}
+
+static void
+parole_gst_query_capabilities (ParoleGst *gst)
+{
+    GstQuery *query;
+    gboolean seekable;
+    
+    query = gst_query_new_seeking (GST_FORMAT_TIME);
+    
+    if ( gst_element_query (gst->priv->playbin, query) )
+    {
+	gst_query_parse_seeking (query,
+				 NULL,
+				 &seekable,
+				 NULL,
+				 NULL);
+    }
+    gst_query_unref (query);
+    
+    g_object_set (G_OBJECT (gst->priv->stream),
+	          "seekable", seekable,
+		  NULL);
+}
+
+static void
+parole_gst_query_duration (ParoleGst *gst)
+{
+    gint64 absolute_duration = 0;
+    gdouble duration = 0;
+    
+    GstFormat gst_time = GST_FORMAT_TIME;
+    
+    gst_element_query_duration (gst->priv->playbin, 
+				&gst_time,
+				&absolute_duration);
+    
+    if (gst_time == GST_FORMAT_TIME)
+    {
+	duration =  absolute_duration / ((gdouble) 60 * 1000 * 1000 * 1000);
+	g_object_set (G_OBJECT (gst->priv->stream),
+		      "absolute-duration", absolute_duration,
+		      "duration", duration,
+		      NULL);
+    }
+}
+
+static void
+parole_gst_set_subtitle_font (ParoleGst *gst)
+{
+    gchar *font;
+    
+    g_object_get (G_OBJECT (gst->priv->conf),
+		  "subtitle-font", &font,
+		  NULL);
+    
+    TRACE ("Setting subtitle font %s\n", font);
+    
+    g_object_set (G_OBJECT (gst->priv->playbin),
+		  "subtitle-font-desc", font,
+		  NULL);
+    g_free (font);
+}
+
+static void
+parole_gst_set_subtitle_encoding (ParoleGst *gst)
+{
+    g_object_set (G_OBJECT (gst->priv->playbin), 
+                  "subtitle-encoding", "UTF-8",
+		  NULL);
+}
+
+static void
+parole_gst_load_subtitle (ParoleGst *gst)
+{
+    ParoleMediaFile *file;
+    const gchar *uri;
+    gchar *sub;
+    gchar *sub_uri;
+    gboolean sub_enabled;
+    
+    g_object_get (G_OBJECT (gst->priv->conf),
+		  "enable-subtitle", &sub_enabled,
+		  NULL);
+		  
+    if ( !sub_enabled )
+	return;
+	
+    g_object_get (G_OBJECT (gst->priv->stream),
+		  "media-file", &file,
+		  NULL);
+	
+    uri = parole_media_file_get_uri (file);
+    sub = parole_get_subtitle_path (uri);
+
+    if ( sub )
+    {
+	TRACE ("Found subtitle with path %s", sub);
+	sub_uri = g_filename_to_uri (sub, NULL, NULL);
+	g_object_set (G_OBJECT (gst->priv->playbin),
+		      "suburi", sub_uri,
+		      NULL);
+	g_free (sub);
+	g_free (sub_uri);
+    }
+    g_object_unref (file);
+}
+
+static void
+parole_gst_query_info (ParoleGst *gst)
+{
+    const GList *info = NULL;
+    GObject *obj;
+    GParamSpec *pspec;
+    GEnumValue *val;
+    gint type;
+    gboolean has_video = FALSE;
+    
+    g_object_get (G_OBJECT (gst->priv->playbin),
+		  "stream-info", &info,
+		  NULL);
+		  
+    for ( ; info != NULL; info = info->next )
+    {
+	obj = info->data;
+	
+	g_object_get (obj,
+		      "type", &type,
+		      NULL);
+	
+	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (obj), "type");
+	val = g_enum_get_value (G_PARAM_SPEC_ENUM (pspec)->enum_class, type);
+	
+	if ( g_ascii_strcasecmp (val->value_name, "video") == 0 ||
+	     g_ascii_strcasecmp (val->value_nick, "video") == 0)
+	{
+	    TRACE ("Stream has video");
+	    g_object_set (G_OBJECT (gst->priv->stream),
+			  "has-video", TRUE,
+			  NULL);
+	    has_video = TRUE;
+	}
+	if ( g_ascii_strcasecmp (val->value_name, "audio") == 0 ||
+	     g_ascii_strcasecmp (val->value_nick, "audio") == 0)
+	{
+	    TRACE ("Stream has audio");
+	    g_object_set (G_OBJECT (gst->priv->stream),
+			  "has-audio", TRUE,
+			  NULL);
+	}
+    }
+    
+    if ( !has_video )
+	gtk_widget_queue_draw (GTK_WIDGET (gst));
+}
+
+static void
+parole_gst_update_vis (ParoleGst *gst)
+{
+    gchar *vis_name;
+    
+    g_object_get (G_OBJECT (gst->priv->conf),
+		  "vis-enabled", &gst->priv->with_vis,
+		  "vis-name", &vis_name,
+		  NULL);
+
+    TRACE ("Vis name %s enabled %d\n", vis_name, gst->priv->with_vis);
+    
+    if ( gst->priv->with_vis )
+    {
+	gst->priv->vis_sink = gst_element_factory_make (vis_name, "vis");
+	g_object_set (G_OBJECT (gst->priv->playbin),
+		      "vis-plugin", gst->priv->vis_sink,
+		      NULL);
+    }
+    else
+    {
+	g_object_set (G_OBJECT (gst->priv->playbin),
+		      "vis-plugin", NULL,
+		      NULL);
+	gtk_widget_queue_draw (GTK_WIDGET (gst));
+    }
+
+    gst->priv->update = FALSE;
+    g_free (vis_name);
+}
+
+static void
+parole_gst_evaluate_state (ParoleGst *gst, GstState old, GstState new, GstState pending)
+{
+    TRACE ("State change new %i old %i pending %i", new, old, pending);
+
+    gst->priv->state = new;
+
+    parole_gst_tick (gst);
+
+    if ( gst->priv->update && new == GST_STATE_NULL)
+	parole_gst_update_vis (gst);
+    
+    if ( gst->priv->target == new )
+	parole_gst_set_window_cursor (GTK_WIDGET (gst)->window, NULL);
+
+    if ( gst->priv->target == GST_STATE_PLAYING && pending >= GST_STATE_READY)
+	parole_gst_set_x_overlay (gst);
+    
+    switch (gst->priv->state)
+    {
+	case GST_STATE_PLAYING:
+	    parole_gst_query_duration (gst);
+	    parole_gst_query_capabilities (gst);
+	    parole_gst_query_info (gst);
+	    
+	    g_signal_emit (G_OBJECT (gst), signals [MEDIA_STATE], 0, 
+			   gst->priv->stream, PAROLE_MEDIA_STATE_PLAYING);
+	    break;
+	case GST_STATE_PAUSED:
+	    g_signal_emit (G_OBJECT (gst), signals [MEDIA_STATE], 0, 
+			   gst->priv->stream, PAROLE_MEDIA_STATE_PAUSED);
+	    break;
+	case GST_STATE_READY:
+	    g_signal_emit (G_OBJECT (gst), signals [MEDIA_STATE], 0, 
+			   gst->priv->stream, PAROLE_MEDIA_STATE_STOPPED);
+
+	    if ( gst->priv->target == GST_STATE_PLAYING)
+	    {
+		parole_gst_play_file_internal (gst);
+	    }
+	    else if ( gst->priv->target == GST_STATE_PAUSED)
+	    {
+		parole_gst_change_state (gst, GST_STATE_PAUSED);
+	    }
+	    else if ( gst->priv->target == GST_STATE_READY)
+	    {
+		parole_gst_draw_logo (gst);
+	    }
+	    break;
+	case GST_STATE_NULL:
+	    g_signal_emit (G_OBJECT (gst), signals [MEDIA_STATE], 0, 
+			   gst->priv->stream, PAROLE_MEDIA_STATE_STOPPED);
+	    break;
+	default:
+	    break;
+    }
+}
+
+static void
+parole_gst_handle_element_message (ParoleGst *gst, GstMessage *message)
+{
+    if ( !message->structure )
+	goto out;
+	
+    if ( gst_structure_has_name (message->structure, "prepare-xwindow-id") )
+	parole_gst_set_x_overlay (gst);
+out:
+    ;
+}
+
+static void
+parole_gst_get_meta_data (ParoleGst *gst, GstTagList *tag)
+{
+    gchar *str;
+    
+    if ( gst_tag_list_get_string_index (tag, GST_TAG_TITLE, 0, &str) )
+    {
+	TRACE ("title:%s", str);
+	g_object_set (G_OBJECT (gst->priv->stream),
+		      "title", str,
+		      NULL);
+	g_free (str);
+    }
+    
+    if ( gst_tag_list_get_string_index (tag, GST_TAG_ARTIST, 0, &str) )
+    {
+	TRACE ("artist:%s", str);
+	g_object_set (G_OBJECT (gst->priv->stream),
+		      "artist", str,
+		      NULL);
+	g_free (str);
+    }
+    
+    if ( gst_tag_list_get_string_index (tag, GST_TAG_DATE, 0, &str) )
+    {
+	TRACE ("year:%s", str);
+	g_object_set (G_OBJECT (gst->priv->stream),
+		      "year", str,
+		      NULL);
+	g_free (str);
+    }
+    
+    if ( gst_tag_list_get_string_index (tag, GST_TAG_ALBUM, 0, &str) )
+    {
+	TRACE ("album:%s", str);
+	g_object_set (G_OBJECT (gst->priv->stream),
+		      "album", str,
+		      NULL);
+	g_free (str);
+    }
+    
+    if ( gst_tag_list_get_string_index (tag, GST_TAG_COMMENT, 0, &str) )
+    {
+	TRACE ("comment:%s", str);
+	g_object_set (G_OBJECT (gst->priv->stream),
+		      "comment", str,
+		      NULL);
+	g_free (str);
+    }
+
+    g_signal_emit (G_OBJECT (gst), signals [MEDIA_TAG], 0, gst->priv->stream);
+}
+
+static gboolean
+parole_gst_bus_event (GstBus *bus, GstMessage *msg, gpointer data)
+{
+    ParoleGst *gst;
+    
+    gst = PAROLE_GST (data);
+
+    switch (GST_MESSAGE_TYPE (msg))
+    {
+        case GST_MESSAGE_EOS:
+	    TRACE ("End of stream");
+	    g_signal_emit (G_OBJECT (gst), signals [MEDIA_STATE], 0, 
+			       gst->priv->stream, PAROLE_MEDIA_STATE_FINISHED);
+	    break;
+	case GST_MESSAGE_ERROR:
+	{
+	    GError *error = NULL;
+	    gchar *debug;
+	    parole_gst_set_window_cursor (GTK_WIDGET (gst)->window, NULL);
+	    gst->priv->target = GST_STATE_NULL;
+	    parole_gst_change_state (gst, GST_STATE_NULL);
+	    gst_message_parse_error (msg, &error, &debug);
+	    TRACE ("*** ERROR %s : %s ***", error->message, debug);
+	    g_signal_emit (G_OBJECT (gst), signals [ERROR], 0, error->message);
+	    g_error_free (error);
+	    g_free (debug);
+	    break;
+	}
+	case GST_MESSAGE_BUFFERING:
+	{
+	    gint per = 0;
+	    gst_message_parse_buffering (msg, &per);
+	    TRACE ("Buffering %d %%", per);
+	    g_signal_emit (G_OBJECT (gst), signals [BUFFERING], 0, 
+			   gst->priv->stream, per);
+	    break;
+	}
+	case GST_MESSAGE_STATE_CHANGED:
+	{
+	    GstState old, new, pending;
+	    gst_message_parse_state_changed (msg, &old, &new, &pending);
+	    
+	    if ( GST_MESSAGE_SRC (msg) == GST_OBJECT (gst->priv->playbin) )
+		parole_gst_evaluate_state (gst, old, new, pending);
+	    break;
+	}
+	case GST_MESSAGE_WARNING:
+	    break;
+	case GST_MESSAGE_INFO:
+	    TRACE ("Info message:");
+	    break;
+	case GST_MESSAGE_TAG:
+	{
+	    GstTagList *tag_list;
+	    
+	    TRACE ("Tag message:");
+	    gst_message_parse_tag (msg, &tag_list);
+	    parole_gst_get_meta_data (gst, tag_list);
+	    gst_tag_list_free (tag_list);
+	    break;
+	}
+	case GST_MESSAGE_STATE_DIRTY:
+	    TRACE ("Stream is dirty");
+	    break;
+	case GST_MESSAGE_STEP_DONE:
+	    break;
+	case GST_MESSAGE_CLOCK_PROVIDE:
+	    break;
+	case GST_MESSAGE_CLOCK_LOST:
+	    break;
+	case GST_MESSAGE_NEW_CLOCK:
+	    break;
+	case GST_MESSAGE_STRUCTURE_CHANGE:
+	    break;
+	case GST_MESSAGE_STREAM_STATUS:
+	    TRACE ("Stream status");
+	    break;
+	case GST_MESSAGE_APPLICATION:
+	    TRACE ("Application message");
+	    break;
+	case GST_MESSAGE_ELEMENT:
+	    parole_gst_handle_element_message (gst, msg);
+	    break;
+	case GST_MESSAGE_SEGMENT_START:
+	    break;
+	case GST_MESSAGE_DURATION:
+	    break;
+	case GST_MESSAGE_LATENCY:
+	    break;
+	case GST_MESSAGE_ASYNC_START:
+	    break;
+	case GST_MESSAGE_ASYNC_DONE:
+	    break;
+        default:
+            break;
+    }
+    return TRUE;
+}
+
+static void
+parole_gst_change_state (ParoleGst *gst, GstState new)
+{
+    GstStateChangeReturn ret;
+
+    ret = gst_element_set_state (GST_ELEMENT (gst->priv->playbin), new);
+    
+    switch (ret)
+    {
+	case GST_STATE_CHANGE_SUCCESS:
+	    parole_gst_evaluate_state (gst, 
+				       GST_STATE_RETURN (gst->priv->playbin),
+				       GST_STATE (gst->priv->playbin),
+				       GST_STATE_PENDING (gst->priv->playbin));
+	    break;
+	case GST_STATE_CHANGE_ASYNC:
+	    TRACE ("State will change async");
+	    break;
+	case GST_STATE_CHANGE_FAILURE:
+	    gst->priv->target = GST_STATE_NULL;
+	    parole_gst_change_state (gst, GST_STATE_NULL);
+	    g_signal_emit (G_OBJECT (gst), signals [ERROR], 0, _("Error in changing state to ready"));
+	    break;
+	case GST_STATE_CHANGE_NO_PREROLL:
+	    TRACE ("State change no_preroll");
+	    break;
+	default:
+	    break;
+    }
+}
+
+static void
+parole_gst_play_file_internal (ParoleGst *gst)
+{
+    ParoleMediaFile *file;
+    
+    TRACE ("Start");
+    
+    if ( G_UNLIKELY (GST_STATE (gst->priv->playbin) == GST_STATE_PLAYING ) )
+    {
+	TRACE ("*** Error *** This is a bug, playbin element is already playing");
+    }
+    
+    g_object_get (G_OBJECT (gst->priv->stream),
+		  "media-file", &file,
+		  NULL);
+    
+    g_object_set (G_OBJECT (gst->priv->playbin),
+		  "uri", parole_media_file_get_uri (file),
+		  "suburi", NULL,
+		  NULL);
+
+    parole_gst_load_subtitle (gst);
+	    
+    parole_gst_change_state (gst, GST_STATE_PLAYING);
+    g_object_unref (file);
+}
+
+static void
+parole_gst_construct (GObject *object)
+{
+    ParoleGst *gst;
+    GstBus *bus;
+    
+    gst = PAROLE_GST (object);
+    
+    gst->priv->playbin = gst_element_factory_make ("playbin", "player");
+ 
+    if ( G_UNLIKELY (gst->priv->playbin == NULL) )
+    {
+	xfce_err (_("Unable to load playbin GStreamer plugin"
+		    ", check your GStreamer installation"));
+		    
+	g_error ("playbin load failed");
+    }
+    
+    gst->priv->video_sink = gst_element_factory_make ("xvimagesink", "video");
+    
+    if ( G_UNLIKELY (gst->priv->video_sink == NULL) )
+    {
+	g_debug ("xvimagesink not found, trying to load ximagesink"); 
+	gst->priv->video_sink = gst_element_factory_make ("ximagesink", "video");
+	
+	if ( G_UNLIKELY (gst->priv->video_sink == NULL) )
+	{
+	    xfce_err (_("Unable to load video GStreamer plugin"
+		      ", check your GStreamer installation"));
+	    g_error ("ximagesink load failed");
+	}
+    }
+    
+    parole_gst_update_vis (gst);
+    
+    g_object_set (G_OBJECT (gst->priv->playbin),
+		  "video-sink", gst->priv->video_sink,
+		  NULL);
+
+    /*
+     * Listen to the bus events.
+     */
+    bus = gst_pipeline_get_bus (GST_PIPELINE (gst->priv->playbin));
+    gst_bus_add_watch (bus, parole_gst_bus_event, gst);
+    g_object_unref (bus);
+    
+    parole_gst_load_logo (gst);
+    
+    parole_gst_set_subtitle_encoding (gst);
+    parole_gst_set_subtitle_font (gst);
+}
+
+static gboolean
+parole_gst_motion_notify_event (GtkWidget *widget, GdkEventMotion *ev)
+{
+    ParoleGst *gst;
+    gboolean ret = FALSE;
+    
+    gst = PAROLE_GST (widget);
+    
+    g_timer_reset (gst->priv->hidecursor_timer);
+    parole_gst_set_cursor_visible (gst, TRUE);
+    
+    if (GTK_WIDGET_CLASS (parole_gst_parent_class)->motion_notify_event)
+	ret |= GTK_WIDGET_CLASS (parole_gst_parent_class)->motion_notify_event (widget, ev);
+
+    return ret;
+}
+
+static void
+parole_gst_conf_notify_cb (GObject *object, GParamSpec *spec, ParoleGst *gst)
+{
+    if ( !g_strcmp0 ("vis-enabled", spec->name) || !g_strcmp0 ("vis-name", spec->name))
+    {
+	gst->priv->update = TRUE;
+    }
+    else if ( !g_strcmp0 ("subtitle-font", spec->name ) && gst->priv->state >= GST_STATE_PAUSED )
+	parole_gst_set_subtitle_font (gst);
+}
+
+static void
+parole_gst_class_init (ParoleGstClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+    object_class->finalize = parole_gst_finalize;
+    object_class->constructed = parole_gst_construct;
+
+    widget_class->realize = parole_gst_realize;
+    widget_class->show = parole_gst_show;
+    widget_class->size_allocate = parole_gst_size_allocate;
+    widget_class->expose_event = parole_gst_expose_event;
+    widget_class->motion_notify_event = parole_gst_motion_notify_event;
+
+    signals[MEDIA_STATE] = 
+        g_signal_new ("media-state",
+                      PAROLE_TYPE_GST,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParoleGstClass, media_state),
+                      NULL, NULL,
+                      _gmarshal_VOID__OBJECT_ENUM,
+                      G_TYPE_NONE, 2, 
+		      PAROLE_TYPE_STREAM, ENUM_GTYPE_MEDIA_STATE);
+
+    signals[MEDIA_PROGRESSED] = 
+        g_signal_new ("media-progressed",
+                      PAROLE_TYPE_GST,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParoleGstClass, media_progressed),
+                      NULL, NULL,
+                      _gmarshal_VOID__OBJECT_DOUBLE,
+                      G_TYPE_NONE, 2, 
+		      G_TYPE_OBJECT, G_TYPE_DOUBLE);
+    
+    signals [MEDIA_TAG] = 
+        g_signal_new ("media-tag",
+                      PAROLE_TYPE_GST,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParoleGstClass, media_tag),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__OBJECT,
+                      G_TYPE_NONE, 1, 
+		      G_TYPE_OBJECT);
+    
+    signals[BUFFERING] = 
+        g_signal_new ("buffering",
+                      PAROLE_TYPE_GST,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParoleGstClass, buffering),
+                      NULL, NULL,
+                      _gmarshal_VOID__OBJECT_INT,
+                      G_TYPE_NONE, 2, 
+		      G_TYPE_OBJECT, G_TYPE_INT);
+    
+    signals[ERROR] = 
+        g_signal_new ("error",
+                      PAROLE_TYPE_GST,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParoleGstClass, error),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__STRING,
+                      G_TYPE_NONE, 1, 
+		      G_TYPE_STRING);
+    
+    g_type_class_add_private (klass, sizeof (ParoleGstPrivate));
+}
+
+static void
+parole_gst_init (ParoleGst *gst)
+{
+    gst->priv = PAROLE_GST_GET_PRIVATE (gst);
+    
+    gst->priv->state = GST_STATE_VOID_PENDING;
+    gst->priv->target = GST_STATE_VOID_PENDING;
+    gst->priv->lock = g_mutex_new ();
+    gst->priv->stream = parole_stream_new ();
+    gst->priv->tick_id = 0;
+    gst->priv->hidecursor_timer = g_timer_new ();
+    gst->priv->update = FALSE;
+    gst->priv->vis_sink = NULL;
+    
+    gst->priv->conf = parole_conf_new ();
+    
+    g_signal_connect (G_OBJECT (gst->priv->conf), "notify",
+		      G_CALLBACK (parole_gst_conf_notify_cb), gst);
+    
+    GTK_WIDGET_SET_FLAGS (GTK_WIDGET (gst), GTK_CAN_FOCUS);
+    
+    /*
+     * Disable double buffering on the video output to avoid
+     * flickering when resizing the window.
+     */
+    GTK_WIDGET_UNSET_FLAGS (GTK_WIDGET (gst), GTK_DOUBLE_BUFFERED);
+}
+
+GtkWidget *
+parole_gst_new (void)
+{
+    static gpointer parole_gst_object = NULL;
+    
+    if ( G_LIKELY (parole_gst_object != NULL ) )
+    {
+	//g_object_ref (parole_gst_object);
+    }
+    else
+    {
+	parole_gst_object = g_object_new (PAROLE_TYPE_GST, NULL);
+	g_object_add_weak_pointer (parole_gst_object, &parole_gst_object);
+    }
+    
+    return GTK_WIDGET (parole_gst_object);
+}
+
+void parole_gst_play_file (ParoleGst *gst, ParoleMediaFile *file)
+{
+    g_mutex_lock (gst->priv->lock);
+    
+    gst->priv->target = GST_STATE_PLAYING;
+    
+    parole_stream_init_properties (gst->priv->stream);
+    
+    g_object_set (G_OBJECT (gst->priv->stream),
+	          "media-file", g_object_ref (file),
+		  NULL);
+
+    g_mutex_unlock (gst->priv->lock);
+    
+    parole_window_busy_cursor (GTK_WIDGET (gst)->window);
+    
+    if ( gst->priv->state < GST_STATE_PAUSED )
+	parole_gst_play_file_internal (gst);
+    else if ( gst->priv->update )
+	parole_gst_change_state (gst, GST_STATE_NULL);
+    else 
+	parole_gst_change_state (gst, GST_STATE_READY);
+}
+
+void parole_gst_pause (ParoleGst *gst)
+{
+    g_mutex_lock (gst->priv->lock);
+    
+    gst->priv->target = GST_STATE_PAUSED;
+    
+    g_mutex_unlock (gst->priv->lock);
+
+    parole_window_busy_cursor (GTK_WIDGET (gst)->window);
+    parole_gst_change_state (gst, GST_STATE_PAUSED);
+}
+
+void parole_gst_resume (ParoleGst *gst)
+{
+    g_mutex_lock (gst->priv->lock);
+    
+    gst->priv->target = GST_STATE_PLAYING;
+    
+    g_mutex_unlock (gst->priv->lock);
+
+    parole_window_busy_cursor (GTK_WIDGET (gst)->window);
+    parole_gst_change_state (gst, GST_STATE_PLAYING);
+}
+
+void parole_gst_stop (ParoleGst *gst)
+{
+    g_mutex_lock (gst->priv->lock);
+    
+    parole_stream_init_properties (gst->priv->stream);
+    gst->priv->target = GST_STATE_READY;
+    
+    g_mutex_unlock (gst->priv->lock);
+
+    parole_window_busy_cursor (GTK_WIDGET (gst)->window);
+    
+    parole_gst_change_state (gst, GST_STATE_READY);
+}
+
+void parole_gst_null_state (ParoleGst *gst)
+{
+    g_mutex_lock (gst->priv->lock);
+    
+    parole_stream_init_properties (gst->priv->stream);
+    gst->priv->target = GST_STATE_NULL;
+    
+    g_mutex_unlock (gst->priv->lock);
+
+    parole_window_busy_cursor (GTK_WIDGET (gst)->window);
+    
+    parole_gst_change_state (gst, GST_STATE_NULL);
+}
+
+void parole_gst_seek (ParoleGst *gst, gdouble pos)
+{
+    gint64 seek;
+    gint64 absolute_duration;
+    gdouble duration;
+    gboolean seekable;
+    gboolean ret;
+
+    TRACE ("Seeking");
+
+    g_object_get (G_OBJECT (gst->priv->stream),
+		  "absolute-duration", &absolute_duration,
+		  "duration", &duration,
+		  "seekable", &seekable,
+		  NULL);
+		  
+#ifdef DEBUG
+    g_return_if_fail (duration != 0);
+    g_return_if_fail (absolute_duration != 0);
+    g_return_if_fail (seekable == TRUE);
+#endif
+	
+    seek = (gint64) (pos * absolute_duration) / duration;
+    
+    ret = gst_element_seek (gst->priv->playbin,
+			    1.0,
+			    GST_FORMAT_TIME,
+			    GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_FLUSH,
+			    GST_SEEK_TYPE_SET, seek,
+			    GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
+			    
+    if ( !ret )
+    {
+	g_warning ("Failed to seek element");
+    }
+}
+
+void parole_gst_set_volume (ParoleGst *gst, gdouble value)
+{
+    g_object_set (G_OBJECT (gst->priv->playbin),
+		  "volume", value,
+		  NULL);
+}
+						    
+gdouble	parole_gst_get_volume (ParoleGst *gst)
+{
+    gdouble volume;
+    
+    g_object_get (G_OBJECT (gst->priv->playbin),
+		  "volume", &volume,
+		  NULL);
+    return volume;
+}

Added: parole/trunk/parole/parole-gst.h
===================================================================
--- parole/trunk/parole/parole-gst.h	                        (rev 0)
+++ parole/trunk/parole/parole-gst.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,106 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_GST_H
+#define __PAROLE_GST_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "parole-stream.h"
+#include "parole-mediafile.h"
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_GST        (parole_gst_get_type () )
+#define PAROLE_GST(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_GST, ParoleGst))
+#define PAROLE_IS_GST(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_GST))
+
+/*
+ * Keep this order to be compatible with the ParoleState enum
+ * used by the plugin interface.
+ */
+typedef enum /*< prefix=PAROLE_MEDIA_STATE_ >*/
+{
+    PAROLE_MEDIA_STATE_STOPPED,
+    PAROLE_MEDIA_STATE_FINISHED,
+    PAROLE_MEDIA_STATE_PAUSED,
+    PAROLE_MEDIA_STATE_PLAYING
+    
+} ParoleMediaState;
+
+typedef struct ParoleGstPrivate ParoleGstPrivate;
+
+typedef struct
+{
+    GtkWidget         	parent;
+    ParoleGstPrivate   *priv;
+    
+} ParoleGst;
+
+typedef struct
+{
+    GtkWidgetClass 	parent_class;
+    
+    void		(*media_state)		 (ParoleGst *gst,
+						  const ParoleStream *stream,
+						  ParoleMediaState state);
+						  
+    void		(*media_progressed)	 (ParoleGst *gst,
+					          const ParoleStream *stream,
+						  gdouble value);
+    
+    void		(*buffering)		 (ParoleGst *gst,
+					          const ParoleStream *stream,
+						  gint percentage);
+    
+    void		(*media_tag)		 (ParoleGst *gst,
+						  const ParoleStream *stream);
+    
+    void		(*error)		 (ParoleGst *gst,
+						  const gchar *error);
+    
+} ParoleGstClass;
+
+GType        		parole_gst_get_type        (void) G_GNUC_CONST;
+GtkWidget      	       *parole_gst_new             (void);
+
+void		        parole_gst_play_file       (ParoleGst *gst,
+					            ParoleMediaFile *file);
+
+void			parole_gst_pause           (ParoleGst *gst);
+
+void			parole_gst_resume          (ParoleGst *gst);
+
+void			parole_gst_stop            (ParoleGst *gst);
+
+void			parole_gst_null_state	   (ParoleGst *gst);
+
+void			parole_gst_seek		   (ParoleGst *gst,
+						    gdouble pos);
+
+void			parole_gst_set_volume      (ParoleGst *gst,
+						    gdouble value);
+						    
+gdouble			parole_gst_get_volume	   (ParoleGst *gst);
+
+G_END_DECLS
+
+#endif /* __PAROLE_GST_H */

Added: parole/trunk/parole/parole-mediachooser.c
===================================================================
--- parole/trunk/parole/parole-mediachooser.c	                        (rev 0)
+++ parole/trunk/parole/parole-mediachooser.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,333 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <gtk/gtk.h>
+#include <glib.h>
+
+#include <libxfce4util/libxfce4util.h>
+#include <libxfcegui4/libxfcegui4.h>
+
+#include "common/parole-builder.h"
+#include "interfaces/mediachooser_ui.h"
+#include "interfaces/openlocation_ui.h"
+
+#include "parole-mediachooser.h"
+
+#include "parole-mediafile.h"
+#include "parole-filters.h"
+#include "parole-rc-utils.h"
+#include "parole-utils.h"
+
+
+/*
+ * GtkBuilder Callbacks
+ */
+void	parole_media_chooser_open 	(GtkWidget *widget, 
+				         ParoleMediaChooser *chooser);
+
+void	parole_media_chooser_close	(GtkWidget *widget,
+					 ParoleMediaChooser *chooser);
+					 
+void	media_chooser_folder_changed_cb (GtkWidget *widget, 
+					 gpointer data);
+
+void	parole_media_chooser_open_location_cb (GtkButton *bt, 
+					       ParoleMediaChooser *chooser);
+
+#define MEDIA_CHOOSER_INTERFACE_FILE INTERFACES_DIR "/mediachooser.ui"
+#define OPEN_LOCATION_INTERFACE_FILE INTERFACES_DIR "/openlocation.ui"
+
+enum
+{
+    MEDIA_FILES_OPENED,
+    MEDIA_FILE_OPENED,
+    LOCATION_OPENED,
+    LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (ParoleMediaChooser, parole_media_chooser, GTK_TYPE_DIALOG)
+
+void
+parole_media_chooser_close (GtkWidget *widget, ParoleMediaChooser *chooser)
+{
+    gtk_widget_destroy (GTK_WIDGET (chooser));
+}
+
+void
+media_chooser_folder_changed_cb (GtkWidget *widget, gpointer data)
+{
+    gchar *folder;
+    folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (widget));
+    
+    if ( folder )
+    {
+	parole_rc_write_entry_string ("media-chooser-folder", folder);
+	g_free (folder);
+    }
+}
+
+static void
+parole_media_chooser_add_many (ParoleMediaChooser *chooser, GtkWidget *file_chooser)
+{
+    GSList *files;
+    GtkFileFilter *filter;
+    gchar *file;
+    guint    i;
+    guint len;
+    
+    files = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (file_chooser));
+    filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (file_chooser));
+    
+    if ( G_UNLIKELY (files == NULL) )
+	return;
+	
+    len = g_slist_length (files);
+    
+    for ( i = 0; i < len; i++)
+    {
+	GSList *media_files = NULL;
+	file = g_slist_nth_data (files, i);
+	parole_get_media_files (filter, file, &media_files);
+	g_signal_emit (G_OBJECT (chooser), signals [MEDIA_FILES_OPENED], 0, media_files);
+	g_slist_free (media_files);
+    }
+    
+    g_slist_foreach (files, (GFunc) g_free, NULL);
+    g_slist_free (files);
+}
+
+void
+parole_media_chooser_open (GtkWidget *widget, ParoleMediaChooser *chooser)
+{
+    ParoleMediaFile *file;
+    GtkWidget *file_chooser;
+    gboolean  multiple;
+    gchar *filename;
+
+    file_chooser = GTK_WIDGET (g_object_get_data (G_OBJECT (chooser), "file-chooser"));
+    
+    multiple = gtk_file_chooser_get_select_multiple (GTK_FILE_CHOOSER (file_chooser));
+    
+    /*
+     * Emit one file opened
+     */
+    if ( multiple == FALSE )
+    {
+	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_chooser));
+	
+	if ( G_LIKELY (filename != NULL ) )
+	{
+	    file = parole_media_file_new (filename);
+	    g_signal_emit (G_OBJECT (chooser), signals [MEDIA_FILE_OPENED], 0, file);
+	    g_free (filename);
+	}
+	parole_media_chooser_close (NULL, chooser);
+    }
+    else
+    {
+	parole_window_busy_cursor (GTK_WIDGET (chooser)->window);
+	parole_media_chooser_add_many (chooser, file_chooser);
+	parole_media_chooser_close (NULL, chooser);
+    }
+}
+
+void
+parole_media_chooser_open_location_cb (GtkButton *bt, ParoleMediaChooser *chooser)
+{
+    ParoleMediaFile *file;
+    GtkWidget *entry;
+    const gchar *location;
+
+    entry = GTK_WIDGET (g_object_get_data (G_OBJECT (chooser), "entry"));
+    location = gtk_entry_get_text (GTK_ENTRY (entry));
+    
+    if ( !location || strlen (location) == 0)
+	goto out;
+
+    TRACE ("Location %s", location);
+
+    file = parole_media_file_new (location);
+    gtk_widget_hide (GTK_WIDGET (chooser));
+    g_signal_emit (G_OBJECT (chooser), signals [MEDIA_FILE_OPENED], 0, file);
+out:
+    parole_media_chooser_close (NULL, chooser);
+}
+
+static void
+parole_media_chooser_open_internal (GtkWidget *chooser, gboolean multiple)
+{
+    ParoleMediaChooser *media_chooser;
+    GtkWidget   *vbox;
+    GtkWidget   *file_chooser;
+    GtkBuilder  *builder;
+    GtkWidget   *open;
+    GtkWidget   *img;
+    const gchar *folder;
+
+    media_chooser = PAROLE_MEDIA_CHOOSER (chooser);
+    
+    builder = parole_builder_new_from_string (mediachooser_ui, mediachooser_ui_length);
+    
+    file_chooser = GTK_WIDGET (gtk_builder_get_object (builder, "filechooserwidget"));
+    
+    vbox = GTK_WIDGET (gtk_builder_get_object (builder, "vbox"));
+    open = GTK_WIDGET (gtk_builder_get_object (builder, "open"));
+    
+    gtk_window_set_title (GTK_WINDOW (chooser), multiple == TRUE ? _("Add media files") : _("Open media file"));
+
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), parole_get_supported_media_filter ());
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), parole_get_supported_audio_filter ());
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), parole_get_supported_video_filter ());
+
+    folder = parole_rc_read_entry_string ("media-chooser-folder", NULL);
+    
+    if ( folder )
+	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_chooser), folder);
+    
+    gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (file_chooser), multiple);
+    
+    img = gtk_image_new_from_stock (multiple ? GTK_STOCK_ADD : GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);
+    
+    g_object_set (G_OBJECT (open),
+		  "image", img,
+		  "label", multiple ? _("Add") : _("Open"),
+		  NULL);
+    
+    g_object_set_data (G_OBJECT (chooser), "file-chooser", file_chooser);
+    
+    gtk_container_add (GTK_CONTAINER (GTK_DIALOG (media_chooser)->vbox), vbox);
+    gtk_builder_connect_signals (builder, chooser);
+    g_signal_connect (chooser, "destroy",
+		      G_CALLBACK (parole_media_chooser_close), chooser);
+		      
+    g_object_unref (builder);
+}
+
+static void
+parole_media_chooser_open_location_internal (GtkWidget *chooser)
+{
+    GtkBuilder *builder;
+    GtkWidget *vbox;
+    GtkWidget *open;
+    GtkWidget *entry;
+    
+    builder = parole_builder_new_from_string (openlocation_ui, openlocation_ui_length);
+    
+    vbox = GTK_WIDGET (gtk_builder_get_object (builder, "vbox"));
+    entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
+    open = GTK_WIDGET (gtk_builder_get_object (builder, "open"));
+    
+    g_object_set_data (G_OBJECT (chooser), "entry", entry);
+    
+    gtk_container_add (GTK_CONTAINER (GTK_DIALOG (chooser)->vbox), vbox);
+    
+    gtk_builder_connect_signals (builder, chooser);
+    g_signal_connect (chooser, "destroy",
+		      G_CALLBACK (parole_media_chooser_close), chooser);
+    g_object_unref (builder);
+}
+
+static void
+parole_media_chooser_finalize (GObject *object)
+{
+    ParoleMediaChooser *parole_media_chooser;
+
+    parole_media_chooser = PAROLE_MEDIA_CHOOSER (object);
+
+    G_OBJECT_CLASS (parole_media_chooser_parent_class)->finalize (object);
+}
+
+static void
+parole_media_chooser_class_init (ParoleMediaChooserClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    signals[MEDIA_FILES_OPENED] = 
+        g_signal_new("media-files-opened",
+                      PAROLE_TYPE_MEDIA_CHOOSER,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParoleMediaChooserClass, media_files_opened),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__POINTER,
+                      G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+    signals[MEDIA_FILE_OPENED] = 
+        g_signal_new("media-file-opened",
+                      PAROLE_TYPE_MEDIA_CHOOSER,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParoleMediaChooserClass, media_file_opened),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__OBJECT,
+                      G_TYPE_NONE, 1, G_TYPE_OBJECT);
+
+    object_class->finalize = parole_media_chooser_finalize;
+}
+
+static void
+parole_media_chooser_init (ParoleMediaChooser *chooser)
+{
+    gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
+}
+
+static GtkWidget *
+parole_media_chooser_new (GtkWidget *parent)
+{
+    ParoleMediaChooser *chooser;
+        
+    chooser = g_object_new (PAROLE_TYPE_MEDIA_CHOOSER, NULL);
+    
+    if ( parent )
+	gtk_window_set_transient_for (GTK_WINDOW (chooser), GTK_WINDOW (parent));
+    
+    return GTK_WIDGET (chooser);
+}
+
+GtkWidget *parole_media_chooser_open_local (GtkWidget *parent, gboolean multiple)
+{
+    GtkWidget *dialog;
+    
+    dialog = parole_media_chooser_new (parent);
+	
+    parole_media_chooser_open_internal (dialog, multiple);
+    gtk_window_set_default_size (GTK_WINDOW (dialog), 680, 480);
+    
+    return dialog;
+}
+
+GtkWidget *parole_media_chooser_open_location (GtkWidget *parent)
+{
+    GtkWidget *dialog;
+    
+    dialog = parole_media_chooser_new (parent);
+	
+    parole_media_chooser_open_location_internal (dialog);
+    
+    return dialog;
+}

Added: parole/trunk/parole/parole-mediachooser.h
===================================================================
--- parole/trunk/parole/parole-mediachooser.h	                        (rev 0)
+++ parole/trunk/parole/parole-mediachooser.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,64 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_MEDIA_CHOOSER_H
+#define __PAROLE_MEDIA_CHOOSER_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include "parole-mediafile.h"
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_MEDIA_CHOOSER        (parole_media_chooser_get_type () )
+#define PAROLE_MEDIA_CHOOSER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_MEDIA_CHOOSER, ParoleMediaChooser))
+#define PAROLE_IS_MEDIA_CHOOSER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_MEDIA_CHOOSER))
+
+typedef struct ParoleMediaChooserPrivate ParoleMediaChooserPrivate;
+
+typedef struct
+{
+    GtkDialog         		 parent;
+    
+} ParoleMediaChooser;
+
+typedef struct
+{
+    GtkDialogClass 		 parent_class;
+    
+    void			 (*media_files_opened)		    (ParoleMediaChooser *chooser,
+								     GPtrArray *array);
+								     
+    void			 (*media_file_opened)		    (ParoleMediaChooser *chooser,
+								     ParoleMediaFile *file);
+    
+} ParoleMediaChooserClass;
+
+GType        			 parole_media_chooser_get_type      (void) G_GNUC_CONST;
+
+GtkWidget			*parole_media_chooser_open_local    (GtkWidget *parent,
+								     gboolean multiple);
+								     
+GtkWidget			*parole_media_chooser_open_location (GtkWidget *parent);
+
+G_END_DECLS
+
+#endif /* __PAROLE_MEDIA_CHOOSER_H */

Added: parole/trunk/parole/parole-mediafile.c
===================================================================
--- parole/trunk/parole/parole-mediafile.c	                        (rev 0)
+++ parole/trunk/parole/parole-mediafile.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,333 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <glib.h>
+#include <gio/gio.h>
+
+#include "parole-mediafile.h"
+
+#define PAROLE_MEDIA_FILE_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_MEDIA_FILE, ParoleMediaFilePrivate))
+
+typedef struct _ParoleMediaFilePrivate ParoleMediaFilePrivate;
+
+struct _ParoleMediaFilePrivate
+{
+    gchar 	*filename;
+    gchar 	*display_name;
+    gchar 	*uri;
+    gchar       *content_type;
+    
+};
+
+enum
+{
+    PROP_0,
+    PROP_PATH,
+    PROP_DISPLAY_NAME,
+    PROP_URI,
+    PROP_CONTENT_TYPE
+};
+
+G_DEFINE_TYPE (ParoleMediaFile, parole_media_file, G_TYPE_OBJECT)
+
+static void
+parole_media_file_finalize (GObject *object)
+{
+    ParoleMediaFile *file;
+    ParoleMediaFilePrivate *priv;
+
+    file = PAROLE_MEDIA_FILE (object);
+    priv = PAROLE_MEDIA_FILE_GET_PRIVATE (file);
+    
+    g_debug ("media file object finalized %s", priv->display_name);
+    
+    if ( priv->filename )
+	g_free (priv->filename);
+
+    if ( priv->uri )
+	g_free (priv->uri);
+	
+    if ( priv->display_name )
+	g_free (priv->display_name);
+	
+    if ( priv->content_type )
+	g_free (priv->content_type);
+    
+    G_OBJECT_CLASS (parole_media_file_parent_class)->finalize (object);
+}
+
+static void
+parole_media_file_set_property (GObject *object, guint prop_id, 
+			      const GValue *value, GParamSpec *pspec)
+{
+    ParoleMediaFile *file;
+    file = PAROLE_MEDIA_FILE (object);
+    
+    switch (prop_id)
+    {
+	case PROP_PATH:
+	    PAROLE_MEDIA_FILE_GET_PRIVATE (file)->filename = g_strdup (g_value_get_string (value));
+	    break;
+	default:
+	    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	    break;
+    }
+}
+
+static void
+parole_media_file_get_property (GObject *object, guint prop_id, 
+			      GValue *value, GParamSpec *pspec)
+{
+    ParoleMediaFile *file;
+
+    file = PAROLE_MEDIA_FILE (object);
+    
+    switch (prop_id)
+    {
+	case PROP_PATH:
+	    g_value_set_string (value, PAROLE_MEDIA_FILE_GET_PRIVATE (file)->filename);
+	    break;
+	case PROP_URI:
+	    g_value_set_string (value, PAROLE_MEDIA_FILE_GET_PRIVATE (file)->filename);
+	    break;
+	case PROP_CONTENT_TYPE:
+	    g_value_set_string (value, PAROLE_MEDIA_FILE_GET_PRIVATE (file)->content_type);
+	    break;
+	case PROP_DISPLAY_NAME:
+	    g_value_set_string (value, PAROLE_MEDIA_FILE_GET_PRIVATE (file)->display_name);
+	    break;
+	default:
+	    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	    break;
+    }
+}
+
+static void
+parole_media_file_constructed (GObject *object)
+{
+    GFile *gfile;
+    GFileInfo *info;
+    ParoleMediaFile *file;
+    ParoleMediaFilePrivate *priv;
+    GError *error = NULL;
+    
+    file = PAROLE_MEDIA_FILE (object);
+    priv = PAROLE_MEDIA_FILE_GET_PRIVATE (file);
+    
+    gfile = g_file_new_for_commandline_arg (priv->filename);
+
+    info = g_file_query_info (gfile, 
+			      "standard::*,",
+			      0,
+			      NULL,
+			      &error);
+
+    if ( error )
+    {
+	if ( G_LIKELY (error->code == G_IO_ERROR_NOT_SUPPORTED) )
+	{
+	    g_error_free (error);
+	    priv->display_name = g_file_get_basename (gfile);
+	}
+	else
+	{
+	    priv->display_name = g_strdup (priv->filename);
+	}
+	g_warning ("Unable to read file info %s", error->message);
+	goto out;
+    }
+
+    priv->display_name = g_strdup (g_file_info_get_display_name (info));
+    priv->content_type = g_strdup (g_file_info_get_content_type (info));
+    
+    g_object_unref (info);
+out:
+    priv->uri = g_file_get_uri (gfile);
+    g_object_unref (gfile);
+}
+
+static void
+parole_media_file_class_init (ParoleMediaFileClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_media_file_finalize;
+    
+    object_class->constructed = parole_media_file_constructed;
+    object_class->set_property = parole_media_file_set_property;
+    object_class->get_property = parole_media_file_get_property;
+
+    /**
+     * ParoleMediaFile:filename:
+     * 
+     * The filename of the file.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_PATH,
+				     g_param_spec_string ("filename",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_CONSTRUCT_ONLY|
+							  G_PARAM_READWRITE));
+
+    /**
+     * ParoleMediaFile:display-name:
+     * 
+     * a UTF-8 name that can be displayed in the UI.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_DISPLAY_NAME,
+				     g_param_spec_string ("display-name",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_READABLE));
+
+    /**
+     * ParoleMediaFile:uri:
+     * 
+     * The Uri of the file.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_URI,
+				     g_param_spec_string ("uri",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_READABLE));
+
+    /**
+     * ParoleMediaFile:content-type:
+     * 
+     * The content type of the file.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_CONTENT_TYPE,
+				     g_param_spec_string ("content-type",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_READABLE));
+
+    g_type_class_add_private (klass, sizeof (ParoleMediaFilePrivate));
+}
+
+static void
+parole_media_file_init (ParoleMediaFile *file)
+{
+    ParoleMediaFilePrivate *priv;
+    
+    priv = PAROLE_MEDIA_FILE_GET_PRIVATE (file);
+
+    priv->filename         = NULL;
+    priv->display_name = NULL;
+    priv->uri          = NULL;
+    priv->content_type    = NULL;
+}
+
+/**
+ * parole_media_file_new:
+ * @filename: filename.
+ * 
+ * 
+ * 
+ * Returns: A new #ParoleMediaFile object.
+ **/
+ParoleMediaFile *
+parole_media_file_new (const gchar *filename)
+{
+    ParoleMediaFile *file = NULL;
+    file = g_object_new (PAROLE_TYPE_MEDIA_FILE, "filename", filename, NULL);
+    return file;
+}
+
+/**
+ * parole_media_file_get_file_name:
+ * @file: a #ParoleMediaFile.
+ *  
+ * 
+ * Returns: A string containing the file name.
+ **/
+const gchar *
+parole_media_file_get_file_name (const ParoleMediaFile *file)
+{
+    g_return_val_if_fail (PAROLE_IS_MEDIA_FILE (file), NULL);
+    
+    return PAROLE_MEDIA_FILE_GET_PRIVATE (file)->filename;
+}
+
+/**
+ * parole_media_file_get_display_name:
+ * @file: a #ParoleMediaFile.
+ *  
+ * 
+ * Returns: A string containing the display name.
+ **/
+const gchar *
+parole_media_file_get_display_name (const ParoleMediaFile *file)
+{
+    g_return_val_if_fail (PAROLE_IS_MEDIA_FILE (file), NULL);
+    
+    return PAROLE_MEDIA_FILE_GET_PRIVATE (file)->display_name;
+}
+
+/**
+ * parole_media_file_get_uri:
+ * @file: a #ParoleMediaFile.
+ *  
+ * 
+ * Returns: A string containing the file uri.
+ **/
+const gchar *
+parole_media_file_get_uri (const ParoleMediaFile *file)
+{
+    g_return_val_if_fail (PAROLE_IS_MEDIA_FILE (file), NULL);
+    
+    return PAROLE_MEDIA_FILE_GET_PRIVATE (file)->uri;
+}
+
+/**
+ * parole_media_file_get_content_type:
+ * @file: a #ParoleMediaFile.
+ *  
+ * 
+ * Returns: A string containing the content type of the file.
+ **/
+const gchar *
+parole_media_file_get_content_type (const ParoleMediaFile *file) 
+{
+    g_return_val_if_fail (PAROLE_IS_MEDIA_FILE (file), NULL);
+    
+    return PAROLE_MEDIA_FILE_GET_PRIVATE (file)->content_type;
+}

Added: parole/trunk/parole/parole-mediafile.h
===================================================================
--- parole/trunk/parole/parole-mediafile.h	                        (rev 0)
+++ parole/trunk/parole/parole-mediafile.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,59 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_MEDIA_FILE_H
+#define __PAROLE_MEDIA_FILE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_MEDIA_FILE        (parole_media_file_get_type () )
+#define PAROLE_MEDIA_FILE(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_MEDIA_FILE, ParoleMediaFile))
+#define PAROLE_IS_MEDIA_FILE(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_MEDIA_FILE))
+
+typedef struct _ParoleMediaFile      ParoleMediaFile;
+typedef struct _ParoleMediaFileClass ParoleMediaFileClass;
+
+struct _ParoleMediaFile
+{
+    GObject         		parent;
+};
+
+struct _ParoleMediaFileClass
+{
+    GObjectClass 		parent_class;
+};
+
+GType        			parole_media_file_get_type        	(void) G_GNUC_CONST;
+
+ParoleMediaFile       	       *parole_media_file_new             	(const gchar *filename);
+
+const gchar   G_CONST_RETURN   *parole_media_file_get_file_name 	(const ParoleMediaFile *file) G_GNUC_PURE;
+
+const gchar   G_CONST_RETURN   *parole_media_file_get_display_name 	(const ParoleMediaFile *file) G_GNUC_PURE;
+
+const gchar   G_CONST_RETURN   *parole_media_file_get_uri 		(const ParoleMediaFile *file) G_GNUC_PURE;
+
+const gchar   G_CONST_RETURN   *parole_media_file_get_content_type      (const ParoleMediaFile *file) G_GNUC_PURE;
+
+G_END_DECLS
+
+#endif /* __PAROLE_MEDIA_FILE_H */

Added: parole/trunk/parole/parole-medialist.c
===================================================================
--- parole/trunk/parole/parole-medialist.c	                        (rev 0)
+++ parole/trunk/parole/parole-medialist.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,695 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <gtk/gtk.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <libxfce4util/libxfce4util.h>
+#include <libxfcegui4/libxfcegui4.h>
+
+#include "common/parole-builder.h"
+#include "interfaces/playlist_ui.h"
+
+#include "parole-medialist.h"
+#include "parole-mediafile.h"
+#include "parole-mediachooser.h"
+
+#include "parole-filters.h"
+#include "parole-utils.h"
+#include "parole-dbus.h"
+
+static void 	parole_media_list_dbus_class_init (ParoleMediaListClass *klass);
+static void 	parole_media_list_dbus_init 	  (ParoleMediaList      *list);
+
+/*
+ * Callbacks for GtkBuilder
+ */
+void		parole_media_list_media_up_clicked_cb 	(GtkButton *button, 
+							 ParoleMediaList *list);
+							 
+void		parole_media_list_media_down_clicked_cb (GtkButton *button, 
+							 ParoleMediaList *list);
+							 
+void		parole_media_list_add_clicked_cb 	(GtkButton *button, 
+							 ParoleMediaList *list);
+							 
+void		parole_media_list_remove_clicked_cb 	(GtkButton *button, 
+							 ParoleMediaList *list);
+
+void		parole_media_list_row_activated_cb 	(GtkTreeView *view, 
+							 GtkTreePath *path,
+							 GtkTreeViewColumn *col,
+							 ParoleMediaList *list);
+
+void		parole_media_list_cursor_changed_cb 	(GtkTreeView *view, 
+							 ParoleMediaList *list);
+
+gboolean	parole_media_list_button_release_event  (GtkWidget *widget, 
+							 GdkEventButton *ev, 
+							 ParoleMediaList *list);
+							 
+void		parole_media_list_drag_data_received_cb (GtkWidget *widget,
+							 GdkDragContext *drag_context,
+							 gint x,
+							 gint y,
+							 GtkSelectionData *data,
+							 guint info,
+							 guint drag_time,
+							 ParoleMediaList *list);
+/*
+ * End of GtkBuilder callbacks
+ */
+
+
+#define PLAYLIST_FILE INTERFACES_DIR "/playlist.ui"
+
+#define PAROLE_MEDIA_LIST_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_MEDIA_LIST, ParoleMediaListPrivate))
+
+struct ParoleMediaListPrivate
+{
+    GtkWidget 	  	*view;
+    GtkWidget		*box;
+    GtkListStore	*store;
+};
+
+enum
+{
+    MEDIA_ACTIVATED,
+    MEDIA_CURSOR_CHANGED,
+    LAST_SIGNAL
+};
+
+static GtkTargetEntry target_entry[] =
+{
+    { "STRING",        0, 0 },
+    { "text/uri-list", 0, 1 },
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (ParoleMediaList, parole_media_list, GTK_TYPE_VBOX)
+
+static void
+parole_media_list_add (ParoleMediaList *list, ParoleMediaFile *file, gboolean emit)
+{
+    GtkListStore *list_store;
+    GtkTreePath *path;
+    GtkTreeRowReference *row;
+    GtkTreeIter iter;
+			      
+    list_store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (list->priv->view)));
+    
+    gtk_list_store_append (list_store, &iter);
+    
+    gtk_list_store_set (list_store, 
+			&iter, 
+			NAME_COL, parole_media_file_get_display_name (file),
+			DATA_COL, file,
+			-1);
+    
+    if ( emit )
+    {
+	path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), &iter);
+	row = gtk_tree_row_reference_new (GTK_TREE_MODEL (list_store), path);
+	gtk_tree_path_free (path);
+	g_signal_emit (G_OBJECT (list), signals [MEDIA_ACTIVATED], 0, row);
+    }
+    /*
+     * Unref it as the list store will have
+     * a reference anyway.
+     */
+    g_object_unref (file);
+}
+
+static void
+parole_media_list_file_opened_cb (ParoleMediaChooser *chooser, ParoleMediaFile *file, ParoleMediaList *list)
+{
+    parole_media_list_add (list, file, TRUE);
+}
+
+static void
+parole_media_list_files_opened_cb (ParoleMediaChooser *chooser, GSList *files, ParoleMediaList *list)
+{
+    ParoleMediaFile *file;
+    guint len;
+    guint i;
+    
+    len = g_slist_length (files);
+    
+    for ( i = 0; i < len; i++)
+    {
+	file = g_slist_nth_data (files, i);
+	parole_media_list_add (list, file, FALSE);
+    }
+}
+
+static void
+parole_media_list_open_internal (ParoleMediaList *list, gboolean multiple)
+{
+    GtkWidget *chooser;
+    
+    chooser = parole_media_chooser_open_local (gtk_widget_get_toplevel (GTK_WIDGET (list)), 
+					       multiple);
+					       
+    if ( multiple )
+	g_signal_connect (G_OBJECT (chooser), "media_files_opened",
+		          G_CALLBACK (parole_media_list_files_opened_cb), list);
+    else
+	g_signal_connect (G_OBJECT (chooser), "media_file_opened",
+		          G_CALLBACK (parole_media_list_file_opened_cb), list);
+    
+    gtk_widget_show_all (GTK_WIDGET (chooser));
+}
+
+static void
+parole_media_list_open_location_internal (ParoleMediaList *list)
+{
+    GtkWidget *chooser;
+    
+    chooser = parole_media_chooser_open_location (gtk_widget_get_toplevel (GTK_WIDGET (list)));
+					       
+    g_signal_connect (G_OBJECT (chooser), "media_file_opened",
+		          G_CALLBACK (parole_media_list_file_opened_cb), list);
+    
+    gtk_widget_show_all (GTK_WIDGET (chooser));
+}
+
+static gboolean
+parole_media_list_add_by_path (ParoleMediaList *list, const gchar *path, gboolean emit)
+{
+    GSList *file_list = NULL;
+    GtkFileFilter *filter;
+    ParoleMediaFile *file;
+    guint len;
+    gboolean ret = FALSE;
+    
+    filter = parole_get_supported_media_filter ();
+    g_object_ref_sink (filter);
+    
+    parole_get_media_files (filter, path, &file_list);
+    
+    for ( len = 0; len < g_slist_length (file_list); len++)
+    {
+	file = g_slist_nth_data (file_list, len);
+	parole_media_list_add (list, file, len == 0 ? emit : FALSE);
+	ret = TRUE;
+    }
+    
+    g_object_unref (filter);
+    g_slist_free (file_list);
+    return ret;
+}
+
+void	parole_media_list_drag_data_received_cb (GtkWidget *widget,
+						 GdkDragContext *drag_context,
+						 gint x,
+						 gint y,
+						 GtkSelectionData *data,
+						 guint info,
+						 guint drag_time,
+						 ParoleMediaList *list)
+{
+    gchar **uri_list;
+    gchar *path;
+    guint i;
+    guint added = 0;
+    
+    parole_window_busy_cursor (GTK_WIDGET (list)->window);
+    
+    uri_list = g_uri_list_extract_uris ((const gchar *)data->data);
+    
+    for ( i = 0; uri_list[i] != NULL; i++)
+    {
+	path = g_filename_from_uri (uri_list[i], NULL, NULL);
+	if ( parole_media_list_add_by_path (list, path, i == 0 ? TRUE : FALSE) )
+	    added++;
+
+	g_free (path);
+    }
+
+    g_strfreev (uri_list);
+
+    gdk_window_set_cursor (GTK_WIDGET (list)->window, NULL);
+    gtk_drag_finish (drag_context, added == i ? TRUE : FALSE, FALSE, drag_time);
+}
+
+void
+parole_media_list_add_clicked_cb (GtkButton *button, ParoleMediaList *list)
+{
+    parole_media_list_open_internal (list, TRUE);
+}
+
+void
+parole_media_list_remove_clicked_cb (GtkButton *button, ParoleMediaList *list)
+{
+    GtkTreeSelection *sel;
+    GtkTreeIter iter;
+    
+    sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (list->priv->view));
+    
+    if ( !gtk_tree_selection_get_selected (sel, NULL, &iter) )
+	return;
+	
+    gtk_list_store_remove (list->priv->store,
+			   &iter);
+
+    /*
+     * Returns the number of children that iter has. 
+     * As a special case, if iter is NULL, 
+     * then the number of toplevel nodes is returned. Gtk API doc.
+     */
+    if ( gtk_tree_model_iter_n_children (GTK_TREE_MODEL (list->priv->store), NULL) == 0 )
+	/*
+	 * Will emit the signal media_cursor_changed with FALSE because there is no any 
+	 * row remaining so the player can disable click on the play button.
+	 */
+	g_signal_emit (G_OBJECT (list), signals [MEDIA_CURSOR_CHANGED], 0, FALSE);
+}
+
+void
+parole_media_list_media_down_clicked_cb (GtkButton *button, ParoleMediaList *list)
+{
+    GtkTreeSelection *sel;
+    GtkTreeIter iter;
+    GtkTreeIter *pos_iter;
+    
+    sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (list->priv->view));
+    
+    if ( !gtk_tree_selection_get_selected (sel, NULL, &iter) )
+	return;
+    
+    /* Save the selected iter to the selected row */
+    pos_iter = gtk_tree_iter_copy (&iter);
+
+    /* We are on the last node in the list!*/
+    if ( !gtk_tree_model_iter_next (GTK_TREE_MODEL (list->priv->store), &iter) )
+    {
+	/* Return false if tree is empty*/
+	if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list->priv->store), &iter))
+	{
+	    gtk_list_store_move_before (GTK_LIST_STORE (list->priv->store), pos_iter, &iter);
+	}
+    }
+    else
+    {
+	gtk_list_store_move_after (GTK_LIST_STORE (list->priv->store), pos_iter, &iter);
+    }
+    
+    gtk_tree_iter_free (pos_iter);
+}
+
+void
+parole_media_list_media_up_clicked_cb (GtkButton *button, ParoleMediaList *list)
+{
+    GtkTreeSelection *sel;
+    GtkTreeIter iter;
+    GtkTreePath *path;
+    GtkTreeIter *pos_iter;
+    
+    sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (list->priv->view));
+    
+    if ( !gtk_tree_selection_get_selected (sel, NULL, &iter) )
+	return;
+	
+    /* Save the selected iter to the selected row */
+    pos_iter = gtk_tree_iter_copy (&iter);
+    
+    path = gtk_tree_model_get_path (GTK_TREE_MODEL (list->priv->store), &iter);
+    
+    /* We are on the top of the list */
+    if ( !gtk_tree_path_prev (path) )
+    {
+	/* Passing NULL as the last argument will cause this call to move 
+	 * the iter to the end of the list, Gtk API doc*/
+	gtk_list_store_move_before (GTK_LIST_STORE (list->priv->store), &iter, NULL);
+    }
+    else
+    {
+	if (gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->store), &iter, path))
+	    gtk_list_store_move_before (GTK_LIST_STORE (list->priv->store), pos_iter, &iter);
+    }
+    
+    gtk_tree_path_free (path);
+    gtk_tree_iter_free (pos_iter);
+}
+
+void
+parole_media_list_row_activated_cb (GtkTreeView *view, GtkTreePath *path, 
+				    GtkTreeViewColumn *col, ParoleMediaList *list)
+{
+    GtkTreeModel *model;
+    GtkTreeRowReference *row;
+    
+    model = gtk_tree_view_get_model (GTK_TREE_VIEW (list->priv->view));
+
+    row = gtk_tree_row_reference_new (gtk_tree_view_get_model (GTK_TREE_VIEW (list->priv->view)), 
+				      path);
+				      
+    g_signal_emit (G_OBJECT (list), signals [MEDIA_ACTIVATED], 0, row);
+}
+
+void
+parole_media_list_cursor_changed_cb (GtkTreeView *view, ParoleMediaList *list)
+{
+    GtkTreeSelection *sel;
+    GtkTreeIter iter;
+    
+    sel = gtk_tree_view_get_selection (view);
+    
+    if ( !gtk_tree_selection_get_selected (sel, NULL, &iter ) )
+    {
+	g_signal_emit (G_OBJECT (list), signals [MEDIA_CURSOR_CHANGED], 0, FALSE);
+    }
+    else
+    {
+	g_signal_emit (G_OBJECT (list), signals [MEDIA_CURSOR_CHANGED], 0, TRUE);
+    }
+}
+
+static void
+parole_media_list_clear_list (ParoleMediaList *list)
+{
+    gtk_list_store_clear (GTK_LIST_STORE (list->priv->store));
+}
+
+static void
+parole_media_list_show_menu (ParoleMediaList *list, guint button, guint activate_time)
+{
+    GtkWidget *menu, *mi;
+    
+    menu = gtk_menu_new ();
+    
+    mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL);
+    gtk_widget_set_sensitive (mi, TRUE);
+    gtk_widget_show (mi);
+    g_signal_connect_swapped (mi, "activate",
+                              G_CALLBACK (parole_media_list_clear_list), list);
+			      
+    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);
+}
+
+gboolean
+parole_media_list_button_release_event (GtkWidget *widget, GdkEventButton *ev, ParoleMediaList *list)
+{
+    if ( ev->button == 3 )
+    {
+	parole_media_list_show_menu (list, ev->button, ev->time);
+	return TRUE;
+    }
+    
+    return FALSE;
+}
+
+static void
+parole_media_list_finalize (GObject *object)
+{
+    ParoleMediaList *list;
+
+    list = PAROLE_MEDIA_LIST (object);
+
+    G_OBJECT_CLASS (parole_media_list_parent_class)->finalize (object);
+}
+
+static void
+parole_media_list_class_init (ParoleMediaListClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_media_list_finalize;
+    
+    signals[MEDIA_ACTIVATED] = 
+        g_signal_new ("media-activated",
+                      PAROLE_TYPE_MEDIA_LIST,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParoleMediaListClass, media_activated),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__POINTER,
+                      G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+    signals[MEDIA_CURSOR_CHANGED] = 
+        g_signal_new ("media-cursor-changed",
+                      PAROLE_TYPE_MEDIA_LIST,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParoleMediaListClass, media_cursor_changed),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__BOOLEAN,
+                      G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+
+    g_type_class_add_private (klass, sizeof (ParoleMediaListPrivate));
+    
+    parole_media_list_dbus_class_init (klass);
+}
+
+static void
+parole_media_list_setup_view (ParoleMediaList *list)
+{
+    GtkListStore *list_store;
+    GtkTreeViewColumn *col;
+    GtkCellRenderer *renderer;
+
+    list_store = gtk_list_store_new (COL_NUMBERS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_OBJECT);
+
+    gtk_tree_view_set_model (GTK_TREE_VIEW (list->priv->view), GTK_TREE_MODEL(list_store));
+    
+    gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (list->priv->view), TRUE);
+    col = gtk_tree_view_column_new ();
+
+    renderer = gtk_cell_renderer_pixbuf_new ();
+    
+    gtk_tree_view_column_pack_start(col, renderer, FALSE);
+    gtk_tree_view_column_set_attributes(col, renderer, "pixbuf", PIXBUF_COL, NULL);
+
+    renderer = gtk_cell_renderer_text_new();
+    
+    gtk_tree_view_column_pack_start (col, renderer, TRUE);
+    gtk_tree_view_column_set_attributes (col, renderer, "text", NAME_COL, NULL);
+    g_object_set (renderer, 
+		  "ellipsize", PANGO_ELLIPSIZE_END, 
+		  NULL);
+    
+    gtk_tree_view_append_column (GTK_TREE_VIEW (list->priv->view), col);
+    gtk_tree_view_column_set_title (col, _("Media list"));
+
+    gtk_drag_dest_set (list->priv->view, GTK_DEST_DEFAULT_ALL, target_entry, G_N_ELEMENTS (target_entry),
+                       GDK_ACTION_COPY | GDK_ACTION_MOVE);
+    
+    list->priv->store = list_store;
+}
+
+static void
+parole_media_list_init (ParoleMediaList *list)
+{
+    GtkBuilder *builder;
+    GtkWidget  *box;
+    
+    list->priv = PAROLE_MEDIA_LIST_GET_PRIVATE (list);
+    
+    builder = parole_builder_new_from_string (playlist_ui, playlist_ui_length);
+    
+    list->priv->view = GTK_WIDGET (gtk_builder_get_object (builder, "media-list"));
+    box = GTK_WIDGET (gtk_builder_get_object (builder, "playlist-box"));
+    
+    parole_media_list_setup_view (list);
+    
+    gtk_builder_connect_signals (builder, list);
+
+    gtk_box_pack_start (GTK_BOX (list), box, TRUE, TRUE, 0);
+
+    g_object_unref (builder);
+    
+    gtk_widget_show_all (GTK_WIDGET (list));
+    
+    parole_media_list_dbus_init (list);
+}
+
+GtkWidget *
+parole_media_list_new (void)
+{
+    static gpointer list = NULL;
+    
+    if ( G_LIKELY (list != NULL ) )
+    {
+	g_object_ref (list);
+    }
+    else
+    {
+	list = g_object_new (PAROLE_TYPE_MEDIA_LIST, NULL);
+	g_object_add_weak_pointer (list, &list);
+    }
+    
+    return GTK_WIDGET (list);
+}
+
+/*
+ * Public functions.
+ * 
+ */
+GtkTreeRowReference *parole_media_list_get_next_row (ParoleMediaList *list, GtkTreeRowReference *row)
+{
+    GtkTreeRowReference *next;
+    GtkTreePath *path;
+    GtkTreeIter iter;
+    
+    g_return_val_if_fail (row != NULL, NULL);
+
+    if ( !gtk_tree_row_reference_valid (row) )
+	return NULL;
+    
+    path = gtk_tree_row_reference_get_path (row);
+    
+    gtk_tree_path_next (path);
+    
+    if ( gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->store), &iter, path))
+    {
+	path = gtk_tree_model_get_path (GTK_TREE_MODEL (list->priv->store), &iter);
+	next = gtk_tree_row_reference_new (GTK_TREE_MODEL (list->priv->store), path);
+	gtk_tree_path_free (path);
+	return next;
+    }
+    
+    return NULL;
+}
+
+GtkTreeRowReference *parole_media_list_get_selected_row (ParoleMediaList *list)
+{
+    GtkTreeModel *model;
+    GtkTreePath	*path;
+    GtkTreeSelection *sel;
+    GtkTreeRowReference *row;
+    GtkTreeIter iter;
+    
+    sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (list->priv->view));
+    
+    if (!gtk_tree_selection_get_selected (sel, &model, &iter))
+	return NULL;
+    
+    path = gtk_tree_model_get_path (model, &iter);
+    
+    row = gtk_tree_row_reference_new (model, path);
+    
+    gtk_tree_path_free (path);
+
+    return row;
+}
+
+void parole_media_list_set_row_pixbuf  (ParoleMediaList *list, GtkTreeRowReference *row, GdkPixbuf *pix)
+{
+    GtkTreeIter iter;
+    GtkTreePath *path;
+    
+    if ( gtk_tree_row_reference_valid (row) )
+    {
+	path = gtk_tree_row_reference_get_path (row);
+	
+	if ( gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->store), &iter, path) )
+	{
+	    gtk_list_store_set (list->priv->store, &iter, PIXBUF_COL, pix, -1);
+	}
+	gtk_tree_path_free (path);
+    }
+}
+
+void parole_media_list_set_row_name (ParoleMediaList *list, GtkTreeRowReference *row, const gchar *name)
+{
+    GtkTreeIter iter;
+    GtkTreePath *path;
+    
+    if ( gtk_tree_row_reference_valid (row) )
+    {
+	path = gtk_tree_row_reference_get_path (row);
+	
+	if ( gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->store), &iter, path) )
+	{
+	    gtk_list_store_set (list->priv->store, &iter, NAME_COL, name, -1);
+	}
+	gtk_tree_path_free (path);
+    }
+}
+
+void parole_media_list_open (ParoleMediaList *list, gboolean multiple)
+{
+    parole_media_list_open_internal (list, multiple);
+}
+
+void parole_media_list_open_location (ParoleMediaList *list)
+{
+    parole_media_list_open_location_internal (list);
+}
+
+void parole_media_list_add_files (ParoleMediaList *list, gchar **filenames)
+{
+    guint i;
+    
+    for ( i = 0; filenames && filenames[i] != NULL; i++)
+	    parole_media_list_add_by_path (list, filenames[i], i == 0 ? TRUE : FALSE);
+}
+
+static gboolean	 parole_media_list_dbus_add_files (ParoleMediaList *list,
+					           gchar **in_files,
+						   GError **error);
+
+#include "org.parole.media.list.h"
+
+/*
+ * DBus server implementation
+ */
+static void 
+parole_media_list_dbus_class_init (ParoleMediaListClass *klass)
+{
+    dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
+				     &dbus_glib_parole_media_list_object_info);
+}
+
+static void
+parole_media_list_dbus_init (ParoleMediaList *list)
+{
+    dbus_g_connection_register_g_object (parole_g_session_bus_get (),
+					 PAROLE_DBUS_PATH,
+					 G_OBJECT (list));
+}
+
+static gboolean	 parole_media_list_dbus_add_files (ParoleMediaList *list,
+						   gchar **in_files,
+						   GError **error)
+{
+    TRACE ("Adding files for DBus request");
+    
+    parole_media_list_add_files (list, in_files);
+    
+    return TRUE;
+}

Added: parole/trunk/parole/parole-medialist.h
===================================================================
--- parole/trunk/parole/parole-medialist.h	                        (rev 0)
+++ parole/trunk/parole/parole-medialist.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,90 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_MEDIA_LIST_H
+#define __PAROLE_MEDIA_LIST_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_MEDIA_LIST        (parole_media_list_get_type () )
+#define PAROLE_MEDIA_LIST(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_MEDIA_LIST, ParoleMediaList))
+#define PAROLE_IS_MEDIA_LIST(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_MEDIA_LIST))
+
+enum
+{
+    PIXBUF_COL,
+    NAME_COL,
+    DATA_COL,
+    COL_NUMBERS
+};
+
+typedef struct ParoleMediaListPrivate ParoleMediaListPrivate;
+
+typedef struct
+{
+    GtkVBox         		 parent;
+    
+    ParoleMediaListPrivate     	*priv;
+    
+} ParoleMediaList;
+
+typedef struct
+{
+    GtkVBoxClass  		 parent_class;
+    
+    void			(*media_activated)		    (ParoleMediaList *list,
+								     GtkTreeRowReference *row);
+								  
+    void			(*media_cursor_changed)		    (ParoleMediaList *list,
+								     gboolean media_selected);
+    
+} ParoleMediaListClass;
+
+GType        			 parole_media_list_get_type         (void) G_GNUC_CONST;
+
+GtkWidget       		*parole_media_list_new              (void);
+
+GtkTreeRowReference		*parole_media_list_get_selected_row (ParoleMediaList *list);
+
+GtkTreeRowReference             *parole_media_list_get_next_row     (ParoleMediaList *list,
+								     GtkTreeRowReference *row);
+
+void				 parole_media_list_set_row_pixbuf   (ParoleMediaList *list,
+								     GtkTreeRowReference *row,
+								     GdkPixbuf *pix);
+								     
+void				 parole_media_list_set_row_name     (ParoleMediaList *list,
+							             GtkTreeRowReference *row,
+								     const gchar *name);
+
+void				 parole_media_list_open		    (ParoleMediaList *list,
+								     gboolean multiple);
+
+void			         parole_media_list_open_location    (ParoleMediaList *list);
+
+void				 parole_media_list_add_files        (ParoleMediaList *list,
+								     gchar **filenames);
+
+G_END_DECLS
+
+#endif /* __PAROLE_MEDIA_LIST_H */

Added: parole/trunk/parole/parole-module.c
===================================================================
--- parole/trunk/parole/parole-module.c	                        (rev 0)
+++ parole/trunk/parole/parole-module.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,107 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 "parole-module.h"
+
+G_DEFINE_TYPE (ParoleModule, parole_module, G_TYPE_TYPE_MODULE)
+
+static gboolean
+parole_module_load (GTypeModule *gtype_module)
+{
+    ParoleModule *module;
+    ParolePlugin *plugin;
+    
+    module = PAROLE_MODULE (gtype_module);
+    
+    module->mod = g_module_open (gtype_module->name, G_MODULE_BIND_LOCAL);
+
+    if ( G_UNLIKELY (module->mod == NULL) )
+    {
+	g_critical ("Failed to load plugin : %s", g_module_error ());
+	return FALSE;
+    }
+    
+    if ( !g_module_symbol (module->mod, "parole_plugin_constructor", (gpointer) &module->constructor) )
+    {
+	g_critical ("Plugin %s missing required constructor symbol", gtype_module->name);
+	g_module_close (module->mod);
+	return FALSE;
+    }
+    
+    plugin = (*module->constructor) ();
+    
+    g_object_set_data (G_OBJECT (module), "plugin", plugin);
+    
+    return TRUE;
+}
+
+static void
+parole_module_unload (GTypeModule *gtype_module)
+{
+    ParoleModule *module;
+    ParolePlugin *plugin;
+    
+    module = PAROLE_MODULE (gtype_module);
+
+    plugin = g_object_get_data (G_OBJECT (module), "plugin");
+
+    if (plugin)
+    {
+	g_signal_emit_by_name (G_OBJECT (plugin), "free-data", 0);
+	g_object_unref (plugin);
+    }
+    
+    g_module_close (module->mod);
+    module->constructor = NULL;
+}
+
+static void
+parole_module_class_init (ParoleModuleClass *klass)
+{
+    GTypeModuleClass *gtype_module_class = G_TYPE_MODULE_CLASS (klass);
+
+    gtype_module_class->load   = parole_module_load;
+    gtype_module_class->unload = parole_module_unload;
+}
+
+static void
+parole_module_init (ParoleModule *module)
+{
+}
+
+ParoleModule *
+parole_module_new (const gchar *filename)
+{
+    ParoleModule *module = NULL;
+    
+    module = g_object_new (PAROLE_TYPE_MODULE, NULL);
+    
+    g_type_module_set_name (G_TYPE_MODULE (module), filename);
+    
+    return module;
+}

Added: parole/trunk/parole/parole-module.h
===================================================================
--- parole/trunk/parole/parole-module.h	                        (rev 0)
+++ parole/trunk/parole/parole-module.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,58 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_MODULE_H
+#define __PAROLE_MODULE_H
+
+#include <glib-object.h>
+
+#include "parole-plugin.h"
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_MODULE        (parole_module_get_type () )
+#define PAROLE_MODULE(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_MODULE, ParoleModule))
+#define PAROLE_IS_MODULE(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_MODULE))
+
+typedef struct ParoleModulePrivate ParoleModulePrivate;
+
+typedef struct
+{
+    GTypeModule       	     parent;
+    
+    GModule		    *mod;
+    
+    ParolePlugin	   *(*constructor)		   (void);
+    
+} ParoleModule;
+
+typedef struct
+{
+    GTypeModuleClass 	     parent_class;
+    
+} ParoleModuleClass;
+
+GType        		     parole_module_get_type        (void) G_GNUC_CONST;
+
+ParoleModule       	    *parole_module_new             (const gchar *filename);
+
+G_END_DECLS
+
+#endif /* __PAROLE_MODULE_H */

Added: parole/trunk/parole/parole-player.c
===================================================================
--- parole/trunk/parole/parole-player.c	                        (rev 0)
+++ parole/trunk/parole/parole-player.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,969 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <gtk/gtk.h>
+
+#include <libxfce4util/libxfce4util.h>
+#include <libxfcegui4/libxfcegui4.h>
+
+#include "common/parole-builder.h"
+#include "common/parole-about.h"
+
+#include "parole-player.h"
+#include "parole-sidebar.h"
+#include "parole-gst.h"
+#include "parole-mediachooser.h"
+#include "parole-mediafile.h"
+#include "parole-statusbar.h"
+#include "parole-screensaver.h"
+#include "parole-conf-dialog.h"
+#include "parole-conf.h"
+#include "parole-rc-utils.h"
+#include "parole-utils.h"
+#include "enum-gtypes.h"
+#include "parole-debug.h"
+
+/*
+ * GtkBuilder Callbacks
+ */
+gboolean	parole_player_range_button_press 	(GtkWidget *widget, 
+							 GdkEventButton *ev, 
+							 ParolePlayer *player);
+
+gboolean	parole_player_range_button_release	(GtkWidget *widget,
+							 GdkEventButton *ev,
+							 ParolePlayer *player);
+
+void            parole_player_range_value_changed       (GtkRange *range, 
+							 ParolePlayer *player);
+
+void            parole_player_play_pause_clicked        (GtkButton *button, 
+							 ParolePlayer *player);
+
+void            parole_player_stop_clicked              (GtkButton *button, 
+							 ParolePlayer *player);
+
+void            parole_player_destroy_cb                (GtkObject *window, 
+							 ParolePlayer *player);
+
+gboolean	parole_player_delete_event_cb		(GtkWidget *widget, 
+							 GdkEvent *ev,
+							 ParolePlayer *player);
+
+void		parole_player_show_hide_playlist	(GtkButton *button,
+							 ParolePlayer *player);
+
+/*Menu items callbacks*/
+void            parole_player_menu_open_cb              (GtkWidget *widget, 
+							 ParolePlayer *player);
+
+void            parole_player_menu_open_location_cb     (GtkWidget *widget, 
+							 ParolePlayer *player);
+
+void            parole_player_menu_add_cb               (GtkWidget *widget, 
+							 ParolePlayer *player);
+
+void            parole_player_menu_exit_cb              (GtkWidget *widget,
+							 ParolePlayer *player);
+
+void		parole_player_open_preferences_cb	(GtkWidget *widget,
+							 ParolePlayer *player);
+
+void            parole_player_volume_value_changed_cb   (GtkRange *range, 
+							 ParolePlayer *player);
+
+void		parole_player_full_screen_activated_cb  (GtkWidget *widget,
+							 ParolePlayer *player);
+
+void	        parole_show_about			(GtkWidget *widget);
+
+gboolean	parole_player_key_press 		(GtkWidget *widget, 
+							 GdkEventKey *ev, 
+							 ParolePlayer *player);
+/*
+ * End of GtkBuilder Callbacks
+ */
+
+#define INTERFACE_FILE INTERFACES_DIR "/parole.ui"
+
+#define PAROLE_PLAYER_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_PLAYER, ParolePlayerPrivate))
+
+struct ParolePlayerPrivate
+{
+    ParoleMediaList	*list;
+    ParoleStatusbar     *status;
+    ParoleScreenSaver   *screen_saver;
+    ParoleSidebar       *sidebar;
+
+    GtkWidget 		*gst;
+
+    GtkWidget 		*window;
+    GtkWidget		*playlist_box;
+    GtkWidget		*show_hide_playlist;
+    GtkWidget		*play_pause;
+    GtkWidget		*stop;
+    GtkWidget		*range;
+    
+    GtkWidget		*volume;
+    GtkWidget		*volume_image;
+    GtkWidget		*menu_bar;
+    GtkWidget		*play_box;
+     
+    gboolean             exit;
+    
+    gboolean		 full_screen;
+    
+    ParoleMediaState     state;
+    gboolean		 user_seeking;
+    gboolean             internal_range_change;
+    gboolean		 buffering;
+    
+    GtkTreeRowReference *row;
+        
+};
+
+G_DEFINE_TYPE (ParolePlayer, parole_player, G_TYPE_OBJECT)
+
+void parole_show_about	(GtkWidget *widget)
+{
+    parole_about (_("Parole Media Player"));
+}
+
+void parole_player_show_hide_playlist (GtkButton *button, ParolePlayer *player)
+{
+    GtkWidget *img;
+    gboolean   visible;
+    
+    g_object_get (G_OBJECT (player->priv->show_hide_playlist),
+		  "image", &img,
+		  NULL);
+
+    visible = GTK_WIDGET_VISIBLE (player->priv->playlist_box);
+
+    if ( !visible )
+    {
+	g_object_set (G_OBJECT (img),
+		      "stock", GTK_STOCK_GO_FORWARD,
+		      NULL);
+		      
+	gtk_widget_show_all (player->priv->playlist_box);
+	gtk_widget_set_tooltip_text (GTK_WIDGET (player->priv->show_hide_playlist), _("Hide playlist"));
+    }
+    else
+    {
+	g_object_set (G_OBJECT (img),
+		      "stock", GTK_STOCK_GO_BACK,
+		      NULL);
+		      
+	gtk_widget_hide_all (player->priv->playlist_box);
+	gtk_widget_set_tooltip_text (GTK_WIDGET (player->priv->show_hide_playlist), _("Show playlist"));
+    }
+    g_object_unref (img);
+}
+
+static void
+parole_player_change_range_value (ParolePlayer *player, gdouble value)
+{
+    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_player_media_activated_cb (ParoleMediaList *list, GtkTreeRowReference *row, ParolePlayer *player)
+{
+    ParoleMediaFile *file;
+    GtkTreeIter iter;
+    GtkTreeModel *model;
+
+    parole_player_change_range_value (player, 0);
+
+    if ( player->priv->row )
+    {
+	parole_media_list_set_row_pixbuf (player->priv->list, player->priv->row, NULL);
+	gtk_tree_row_reference_free (player->priv->row);
+	player->priv->row = NULL;
+    }
+    
+    player->priv->row = row;
+    model = gtk_tree_row_reference_get_model (row);
+    
+    if ( gtk_tree_model_get_iter (model, &iter, gtk_tree_row_reference_get_path (row)) )
+    {
+	gtk_tree_model_get (model, &iter, DATA_COL, &file, -1);
+	
+	if ( file )
+	{
+	    TRACE ("Trying to play media file %s", parole_media_file_get_uri (file));
+	    gtk_widget_set_sensitive (player->priv->stop, TRUE);
+	    parole_gst_play_file (PAROLE_GST (player->priv->gst), file);
+	    g_object_unref (file);
+	}
+    }
+}
+
+static void
+parole_player_media_cursor_changed_cb (ParoleMediaList *list, gboolean media_selected, ParolePlayer *player)
+{
+    if (!player->priv->state != PAROLE_MEDIA_STATE_PLAYING)
+	gtk_widget_set_sensitive (player->priv->play_pause, media_selected);
+	
+}
+
+static void
+parole_player_media_progressed_cb (ParoleGst *gst, const ParoleStream *stream, gdouble value, ParolePlayer *player)
+{
+#ifdef DEBUG
+    g_return_if_fail (value > 0);
+#endif
+    
+    if ( !player->priv->user_seeking && player->priv->state == PAROLE_MEDIA_STATE_PLAYING )
+    {
+	parole_player_change_range_value (player, value);
+    }
+    parole_statusbar_set_position (player->priv->status, 
+				   player->priv->state == PAROLE_MEDIA_STATE_PLAYING,
+				   value);
+}
+
+static void
+parole_player_set_playpause_widget_image (GtkWidget *widget, const gchar *stock_id)
+{
+    GtkWidget *img;
+    
+    g_object_get (G_OBJECT (widget),
+		  "image", &img,
+		  NULL);
+		  
+    g_object_set (G_OBJECT (img),
+		  "stock", stock_id,
+		  NULL);
+
+    g_object_unref (img);
+}
+
+static void
+parole_player_set_playpause_button_image (GtkWidget *widget, const gchar *stock_id)
+{
+    GtkWidget *img;
+    
+    g_object_get (G_OBJECT (widget),
+		  "image", &img,
+		  NULL);
+		  
+    g_object_set (G_OBJECT (img),
+		  "stock", stock_id,
+		  NULL);
+
+    g_object_unref (img);
+}
+
+static void
+parole_player_playing (ParolePlayer *player, const ParoleStream *stream)
+{
+    GdkPixbuf *pix = NULL;
+    gdouble duration;
+    gboolean seekable;
+    
+    player->priv->state = PAROLE_MEDIA_STATE_PLAYING;
+    pix = xfce_themed_icon_load ("gtk-media-play-ltr", 16);
+    
+    parole_media_list_set_row_pixbuf (player->priv->list, player->priv->row, pix);
+    
+    g_object_get (G_OBJECT (stream),
+		  "seekable", &seekable,
+		  "duration", &duration,
+		  NULL);
+		  
+    gtk_widget_set_sensitive (player->priv->play_pause, TRUE);
+    gtk_widget_set_sensitive (player->priv->stop, TRUE);
+    
+    parole_player_set_playpause_button_image (player->priv->play_pause, GTK_STOCK_MEDIA_PAUSE);
+    
+    gtk_widget_set_sensitive (player->priv->range, seekable);
+    
+    if ( seekable )
+    {
+	parole_statusbar_set_duration (player->priv->status, duration);
+	gtk_range_set_range (GTK_RANGE (player->priv->range), 0, duration);
+    }
+    else
+    {
+	parole_statusbar_set_text (player->priv->status, _("Playing"));
+	gtk_widget_set_tooltip_text (GTK_WIDGET (player->priv->range), _("Media stream is not seekable"));
+	parole_player_change_range_value (player, 0);
+    }
+
+    if ( pix )
+	g_object_unref (pix);
+}
+
+static void
+parole_player_paused (ParolePlayer *player)
+{
+    GdkPixbuf *pix = NULL;
+    
+    player->priv->state = PAROLE_MEDIA_STATE_PAUSED;
+    
+    TRACE ("Player paused");
+    
+    if ( !player->priv->buffering )
+	parole_statusbar_set_text (player->priv->status, _("Paused"));
+	
+    pix = xfce_themed_icon_load ("gtk-media-pause", 16);
+    parole_media_list_set_row_pixbuf (player->priv->list, player->priv->row, pix);
+    
+    gtk_widget_set_sensitive (player->priv->play_pause, TRUE);
+    gtk_widget_set_sensitive (player->priv->stop, TRUE);
+    
+    parole_player_set_playpause_widget_image (player->priv->play_pause, GTK_STOCK_MEDIA_PLAY);
+    
+    if ( pix )
+	g_object_unref (pix);
+	
+    parole_statusbar_set_text (player->priv->status, _("Paused"));
+}
+
+static void
+parole_player_quit (ParolePlayer *player)
+{
+    gtk_widget_destroy (player->priv->window);
+    g_object_unref (player);
+    gtk_main_quit ();
+}
+
+static void
+parole_player_stopped (ParolePlayer *player)
+{
+    TRACE ("Player stopped");
+    
+    player->priv->state = PAROLE_MEDIA_STATE_STOPPED;
+    
+    parole_statusbar_set_text (player->priv->status, _("Stopped"));
+    
+    gtk_widget_set_sensitive (player->priv->play_pause, FALSE);
+    gtk_widget_set_sensitive (player->priv->stop, FALSE);
+
+    parole_player_change_range_value (player, 0);
+    gtk_widget_set_sensitive (player->priv->range, FALSE);
+
+    parole_player_set_playpause_widget_image (player->priv->play_pause, GTK_STOCK_MEDIA_PLAY);
+    
+    parole_media_list_set_row_pixbuf (player->priv->list, player->priv->row, NULL);
+    
+    if ( player->priv->exit )
+    {
+	parole_player_quit (player);
+    }
+}
+
+static void
+parole_player_play_selected_row (ParolePlayer *player)
+{
+    GtkTreeRowReference *row;
+    
+    row = parole_media_list_get_selected_row (player->priv->list);
+    
+    if ( row )
+    {
+	parole_player_media_activated_cb (player->priv->list, row, player);
+    }
+}
+
+static void
+parole_player_play_next (ParolePlayer *player)
+{
+    GtkTreeRowReference *row;
+    
+    if ( player->priv->row )
+    {
+	parole_media_list_set_row_pixbuf (player->priv->list, player->priv->row, NULL);
+	row = parole_media_list_get_next_row (player->priv->list, player->priv->row);
+	
+	if ( row )
+	{
+	    parole_player_media_activated_cb (player->priv->list, row, player);
+	    return;
+	}
+	else
+	{
+	    TRACE ("No remaining media in the list");
+	    gtk_tree_row_reference_free (player->priv->row);
+	    player->priv->row = NULL;
+	}
+    }
+
+    parole_gst_stop (PAROLE_GST (player->priv->gst));
+}
+
+static void
+parole_player_media_state_cb (ParoleGst *gst, const ParoleStream *stream, ParoleMediaState state, ParolePlayer *player)
+{
+    gboolean has_video;
+    
+    PAROLE_DEBUG_ENUM ("State callback", state, ENUM_GTYPE_MEDIA_STATE);
+    
+    if ( state == PAROLE_MEDIA_STATE_PLAYING && has_video )
+	parole_screen_saver_inhibit (player->priv->screen_saver);
+    else
+	parole_screen_saver_uninhibit (player->priv->screen_saver);
+
+    g_object_get (G_OBJECT (stream),
+		  "has-video", &has_video,
+		  NULL);
+    
+    if ( state == PAROLE_MEDIA_STATE_PLAYING )
+    {
+	parole_player_playing (player, stream);
+    }
+    else if ( state == PAROLE_MEDIA_STATE_PAUSED )
+    {
+	parole_player_paused (player);
+    }
+    else if ( state == PAROLE_MEDIA_STATE_STOPPED )
+    {
+	parole_player_stopped (player);
+    }
+    else if ( state == PAROLE_MEDIA_STATE_FINISHED )
+    {
+	TRACE ("***Playback finished***");
+	parole_player_play_next (player);
+    }
+}
+
+void
+parole_player_play_pause_clicked (GtkButton *button, ParolePlayer *player)
+{
+    if ( player->priv->state == PAROLE_MEDIA_STATE_PLAYING )
+	parole_gst_pause (PAROLE_GST (player->priv->gst));
+    else if ( player->priv->state == PAROLE_MEDIA_STATE_PAUSED )
+	parole_gst_resume (PAROLE_GST (player->priv->gst));
+    else
+	parole_player_play_selected_row (player);
+}
+
+void
+parole_player_stop_clicked (GtkButton *button, ParolePlayer *player)
+{
+    parole_gst_stop (PAROLE_GST (player->priv->gst));
+}
+
+gboolean
+parole_player_range_button_release (GtkWidget *widget, GdkEventButton *ev, ParolePlayer *player)
+{
+    if ( ev->button == 3 )
+    {
+	player->priv->user_seeking = TRUE;
+    }
+    
+    return FALSE;
+}
+
+gboolean
+parole_player_range_button_press (GtkWidget *widget, GdkEventButton *ev, ParolePlayer *player)
+{
+    gdouble value;
+    
+    value = gtk_range_get_value (GTK_RANGE (player->priv->range));
+    
+    if ( ev->button == 3 )
+    {
+	player->priv->user_seeking = FALSE;
+    }
+    
+    return FALSE;
+}
+
+void
+parole_player_range_value_changed (GtkRange *range, ParolePlayer *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 (PAROLE_GST (player->priv->gst), value);
+	player->priv->user_seeking = FALSE;
+    }
+}
+
+static void
+parole_player_error_cb (ParoleGst *gst, const gchar *error, ParolePlayer *player)
+{
+    xfce_err ("%s", error);
+    parole_screen_saver_uninhibit (player->priv->screen_saver);
+    parole_player_stopped (player);
+}
+
+static void
+parole_player_media_tag_cb (ParoleGst *gst, const ParoleStream *stream, ParolePlayer *player)
+{
+    gchar *title;
+    
+    if ( player->priv->row )
+    {
+	g_object_get (G_OBJECT (stream),
+		      "title", &title,
+		      NULL);
+	if ( title )
+	{
+	    parole_media_list_set_row_name (player->priv->list, player->priv->row, title);
+	    g_free (title);
+	}
+    }
+}
+
+static void
+parole_player_buffering_cb (ParoleGst *gst, const ParoleStream *stream, gint percentage, ParolePlayer *player)
+{
+    if ( percentage == 100 )
+    {
+	player->priv->buffering = FALSE;
+	parole_gst_resume (PAROLE_GST (player->priv->gst));
+    }
+    else
+    {
+	player->priv->buffering = TRUE;
+	parole_statusbar_set_buffering (player->priv->status, percentage);
+	
+	if ( player->priv->state == PAROLE_MEDIA_STATE_PLAYING )
+	    parole_gst_pause (PAROLE_GST (player->priv->gst));
+    }
+}
+
+gboolean parole_player_delete_event_cb (GtkWidget *widget, GdkEvent *ev, ParolePlayer *player)
+{
+    parole_window_busy_cursor (GTK_WIDGET (player->priv->window)->window);
+    
+    player->priv->exit = TRUE;
+    parole_gst_null_state (PAROLE_GST (player->priv->gst));
+    
+    return TRUE;
+}
+
+void
+parole_player_destroy_cb (GtkObject *window, ParolePlayer *player)
+{
+}
+
+static void
+parole_player_play_menu_item_activate (ParolePlayer *player)
+{
+    gtk_widget_activate (player->priv->play_pause);
+}
+
+static void
+parole_player_stop_menu_item_activate (ParolePlayer *player)
+{
+    gtk_widget_activate (player->priv->stop);
+}
+
+static void
+parole_player_next_menu_item_activate (ParolePlayer *player)
+{
+    
+}
+
+static void
+parole_player_previous_menu_item_activate (ParolePlayer *player)
+{
+    
+}
+
+static void
+parole_player_full_screen_menu_item_activate (ParolePlayer *player)
+{
+    if ( player->priv->full_screen )
+    {
+	parole_sidebar_set_visible (player->priv->sidebar, TRUE); 
+	parole_statusbar_set_visible (player->priv->status, TRUE);
+	gtk_widget_show (player->priv->play_box);
+	gtk_widget_show (player->priv->menu_bar);
+	gtk_widget_show (player->priv->playlist_box);
+	gtk_window_unfullscreen (GTK_WINDOW (player->priv->window));
+	player->priv->full_screen = FALSE;
+    }
+    else
+    {
+	parole_sidebar_set_visible (player->priv->sidebar, FALSE); 
+	parole_statusbar_set_visible (player->priv->status, FALSE);
+	gtk_widget_hide (player->priv->play_box);
+	gtk_widget_hide (player->priv->menu_bar);
+	gtk_widget_hide (player->priv->playlist_box);
+	gtk_window_fullscreen (GTK_WINDOW (player->priv->window));
+	player->priv->full_screen = TRUE;
+    }
+}
+
+void parole_player_full_screen_activated_cb (GtkWidget *widget, ParolePlayer *player)
+{
+    parole_player_full_screen_menu_item_activate (player);
+}
+
+static void
+parole_player_show_menu (ParolePlayer *player, guint button, guint activate_time)
+{
+    GtkWidget *menu, *mi;
+    gboolean sensitive;
+    
+    menu = gtk_menu_new ();
+    
+    /*Play menu item
+     */
+    mi = gtk_image_menu_item_new_from_stock (player->priv->state == PAROLE_MEDIA_STATE_PLAYING 
+					     ? GTK_STOCK_MEDIA_PAUSE : GTK_STOCK_MEDIA_PLAY, 
+					     NULL);
+					     
+    g_object_get (G_OBJECT (player->priv->play_pause),
+		  "sensitive", &sensitive,
+		  NULL);
+		  
+    gtk_widget_set_sensitive (mi, sensitive);
+    gtk_widget_show (mi);
+    g_signal_connect_swapped (mi, "activate",
+			      G_CALLBACK (parole_player_play_menu_item_activate), player);
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+    
+    /*Stop menu item
+     */
+    mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_MEDIA_STOP, NULL);
+					     
+    gtk_widget_set_sensitive (mi, player->priv->state == PAROLE_MEDIA_STATE_PLAYING);
+    gtk_widget_show (mi);
+    g_signal_connect_swapped (mi, "activate",
+			      G_CALLBACK (parole_player_stop_menu_item_activate), player);
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+    
+    /*Next chapter menu item
+     */
+    mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_MEDIA_NEXT, NULL);
+					     
+    gtk_widget_set_sensitive (mi, player->priv->state == PAROLE_MEDIA_STATE_PLAYING);
+    gtk_widget_show (mi);
+    g_signal_connect_swapped (mi, "activate",
+			      G_CALLBACK (parole_player_next_menu_item_activate), player);
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+    
+    /*Previous chapter menu item
+     */
+    mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_MEDIA_PREVIOUS, NULL);
+					     
+    gtk_widget_set_sensitive (mi, player->priv->state == PAROLE_MEDIA_STATE_PLAYING);
+    gtk_widget_show (mi);
+    g_signal_connect_swapped (mi, "activate",
+			      G_CALLBACK (parole_player_previous_menu_item_activate), player);
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+    
+    mi = gtk_separator_menu_item_new ();
+    gtk_widget_show (mi);
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+    
+    /*
+     * Un/Full screen
+     */
+    mi = gtk_image_menu_item_new_from_stock (player->priv->full_screen ? GTK_STOCK_LEAVE_FULLSCREEN:
+					     GTK_STOCK_FULLSCREEN, NULL);
+    gtk_widget_show (mi);
+    g_signal_connect_swapped (mi, "activate",
+			      G_CALLBACK (parole_player_full_screen_menu_item_activate), 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_player_gst_widget_button_press (GtkWidget *widget, GdkEventButton *ev, ParolePlayer *player)
+{
+    if ( ev->button  == 3)
+    {
+	parole_player_show_menu (player, ev->button, ev->time);
+	return TRUE;
+    }
+    
+    return FALSE;
+}
+
+static gboolean
+parole_player_gst_widget_motion_notify_event (GtkWidget *widget, GdkEventMotion *ev, ParolePlayer *player)
+{
+    gint pointer_y;
+
+    if ( player->priv->full_screen )
+    {
+	pointer_y = (gint) ev->y;
+	if ( pointer_y >= widget->allocation.height - 10 )
+	    gtk_widget_show (player->priv->play_box);
+	else
+	    gtk_widget_hide (player->priv->play_box);
+    }
+    return FALSE;
+}
+
+void
+parole_player_menu_open_cb (GtkWidget *widget, ParolePlayer *player)
+{
+    parole_media_list_open (player->priv->list, FALSE);
+}
+
+void
+parole_player_menu_open_location_cb (GtkWidget *widget, ParolePlayer *player)
+{
+    parole_media_list_open_location (player->priv->list);
+}
+
+void
+parole_player_menu_add_cb (GtkWidget *widget, ParolePlayer *player)
+{
+    parole_media_list_open (player->priv->list, TRUE);
+}
+
+void parole_player_open_preferences_cb	(GtkWidget *widget, ParolePlayer *player)
+{
+    ParoleConfDialog *dialog;
+    
+    dialog = parole_conf_dialog_new ();
+    
+    parole_conf_dialog_open (dialog, player->priv->window);
+}
+
+void
+parole_player_menu_exit_cb (GtkWidget *widget, ParolePlayer *player)
+{
+    parole_player_delete_event_cb (NULL, NULL, player);
+}
+
+static const gchar *
+parole_player_get_volume_icon_name (gdouble value)
+{
+    if ( value == 1. )
+	return "audio-volume-high";
+    else if ( value > 0.5 )
+	return "audio-volume-medium";
+    else if ( value > 0 )
+	return "audio-volume-low";
+    
+    return "audio-volume-muted";
+}
+
+static void
+parole_player_set_volume_image (ParolePlayer *player, gdouble value)
+{
+    GdkPixbuf *icon;
+
+    icon = xfce_themed_icon_load (parole_player_get_volume_icon_name (value), 
+				  player->priv->volume_image->allocation.width);
+    if ( icon )
+    {
+	g_object_set (G_OBJECT (player->priv->volume_image),
+		      "pixbuf", icon,
+		      NULL);
+	gdk_pixbuf_unref (icon);
+    }
+}
+
+static void
+parole_player_change_volume (ParolePlayer *player, gdouble value)
+{
+    parole_gst_set_volume (PAROLE_GST (player->priv->gst), value);
+    parole_player_set_volume_image (player, value);
+}
+
+void
+parole_player_volume_value_changed_cb (GtkRange *range, ParolePlayer *player)
+{
+    gdouble value;
+    value = gtk_range_get_value (range);
+    parole_player_change_volume (player, value);
+    parole_rc_write_entry_int ("volume", (gint)(value * 100));
+}
+
+static void
+parole_player_finalize (GObject *object)
+{
+    ParolePlayer *player;
+
+    player = PAROLE_PLAYER (object);
+
+    TRACE ("start");
+
+    g_object_unref (player->priv->gst);
+    g_object_unref (player->priv->status);
+    g_object_unref (player->priv->screen_saver);
+    g_object_unref (player->priv->sidebar);
+
+    G_OBJECT_CLASS (parole_player_parent_class)->finalize (object);
+}
+
+static void
+parole_player_class_init (ParolePlayerClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_player_finalize;
+
+    g_type_class_add_private (klass, sizeof (ParolePlayerPrivate));
+}
+
+gboolean
+parole_player_key_press (GtkWidget *widget, GdkEventKey *ev, ParolePlayer *player)
+{
+    if ( ev->keyval == GDK_F11 )
+    {
+	parole_player_full_screen_menu_item_activate (player);
+	return TRUE;
+    }
+    
+    return FALSE;
+}
+
+static void
+parole_player_init (ParolePlayer *player)
+{
+    GtkBuilder *builder;
+    
+    player->priv = PAROLE_PLAYER_GET_PRIVATE (player);
+    
+    builder = parole_builder_get_main_interface ();
+    
+    player->priv->gst = parole_gst_new ();
+    /*
+     * Since ParoleGst is derived from GtkWidget and packed in the media output
+     * box the destroy event on the window will destroy the ParoleGst widget
+     * so we ref it to clean up the gst objects before quitting.
+     */
+    g_object_ref (player->priv->gst);
+    player->priv->sidebar = parole_sidebar_new ();
+    player->priv->status = parole_statusbar_new ();
+    player->priv->screen_saver = parole_screen_saver_new ();
+    player->priv->list = PAROLE_MEDIA_LIST (parole_media_list_new ());
+    
+    player->priv->state = PAROLE_MEDIA_STATE_STOPPED;
+    player->priv->user_seeking = FALSE;
+    player->priv->internal_range_change = FALSE;
+    player->priv->exit = FALSE;
+    player->priv->full_screen = FALSE;
+    player->priv->buffering = FALSE;
+    player->priv->row = NULL;
+    
+    /*
+     * Gst signals
+     */
+    g_signal_connect (G_OBJECT (player->priv->gst), "media-state",
+		      G_CALLBACK (parole_player_media_state_cb), player);
+	
+    g_signal_connect (G_OBJECT (player->priv->gst), "media-progressed",
+		      G_CALLBACK (parole_player_media_progressed_cb), player);
+		      
+    g_signal_connect (G_OBJECT (player->priv->gst), "media-tag",
+		      G_CALLBACK (parole_player_media_tag_cb), player);
+    
+    g_signal_connect (G_OBJECT (player->priv->gst), "error",
+		      G_CALLBACK (parole_player_error_cb), player);
+   
+    g_signal_connect (G_OBJECT (player->priv->gst), "buffering",
+		      G_CALLBACK (parole_player_buffering_cb), player);
+    
+    g_signal_connect (G_OBJECT (player->priv->gst), "button-release-event",
+		      G_CALLBACK (parole_player_gst_widget_button_press), player);
+    
+    g_signal_connect (G_OBJECT (player->priv->gst), "motion-notify-event",
+		      G_CALLBACK (parole_player_gst_widget_motion_notify_event), player);
+    
+    player->priv->window = GTK_WIDGET (gtk_builder_get_object (builder, "main-window"));
+    
+    player->priv->play_pause = GTK_WIDGET (gtk_builder_get_object (builder, "play-pause"));
+    player->priv->stop = GTK_WIDGET (gtk_builder_get_object (builder, "stop"));
+    player->priv->range = GTK_WIDGET (gtk_builder_get_object (builder, "scale"));
+    
+    player->priv->volume = GTK_WIDGET (gtk_builder_get_object (builder, "volume"));
+    player->priv->volume_image = GTK_WIDGET (gtk_builder_get_object (builder, "volume-image"));
+    
+    player->priv->menu_bar = GTK_WIDGET (gtk_builder_get_object (builder, "menubar"));
+    player->priv->play_box = GTK_WIDGET (gtk_builder_get_object (builder, "play-box"));
+    player->priv->playlist_box = GTK_WIDGET (gtk_builder_get_object (builder, "notebook-playlist"));
+    player->priv->show_hide_playlist = GTK_WIDGET (gtk_builder_get_object (builder, "show-hide-list"));
+    
+    gtk_range_set_range (GTK_RANGE (player->priv->volume), 0, 1.0);
+    
+    gtk_range_set_value (GTK_RANGE (player->priv->volume), 
+			 (gdouble) (parole_rc_read_entry_int ("volume", 100)/100.));
+    
+    /*
+     * Pack the playlist.
+     */
+    gtk_notebook_append_page (GTK_NOTEBOOK (player->priv->playlist_box), 
+			      GTK_WIDGET (player->priv->list),
+			      gtk_label_new (_("Playlist")));
+    
+    /*
+     * Pack the statusbar.
+     */
+    gtk_widget_show_all (player->priv->window);
+    
+    gtk_box_pack_start (GTK_BOX (gtk_builder_get_object (builder, "output")), 
+			player->priv->gst,
+			TRUE, TRUE, 0);
+    
+    gtk_widget_realize (player->priv->gst);
+    gtk_widget_show (player->priv->gst);
+
+    parole_player_change_volume (player, 
+				 (gdouble) (parole_rc_read_entry_int ("volume", 100)/100.));
+
+    g_signal_connect (player->priv->list, "media_activated",
+		      G_CALLBACK (parole_player_media_activated_cb), player);
+		      
+    g_signal_connect (player->priv->list, "media_cursor_changed",
+		      G_CALLBACK (parole_player_media_cursor_changed_cb), player);
+
+    gtk_builder_connect_signals (builder, player);
+    g_object_unref (builder);
+}
+
+ParolePlayer *
+parole_player_new (void)
+{
+    ParolePlayer *player = NULL;
+    player = g_object_new (PAROLE_TYPE_PLAYER, NULL);
+    return player;
+}
+
+ParoleMediaList	*parole_player_get_media_list (ParolePlayer *player)
+{
+    return player->priv->list;
+}

Added: parole/trunk/parole/parole-player.h
===================================================================
--- parole/trunk/parole/parole-player.h	                        (rev 0)
+++ parole/trunk/parole/parole-player.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,55 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_PLAYER_H
+#define __PAROLE_PLAYER_H
+
+#include <glib-object.h>
+#include "parole-medialist.h"
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_PLAYER        (parole_player_get_type () )
+#define PAROLE_PLAYER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_PLAYER, ParolePlayer))
+#define PAROLE_IS_PLAYER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_PLAYER))
+
+typedef struct ParolePlayerPrivate ParolePlayerPrivate;
+
+typedef struct
+{
+    GObject         		 parent;
+    ParolePlayerPrivate     	*priv;
+    
+} ParolePlayer;
+
+typedef struct
+{
+    GObjectClass 		 parent_class;
+    
+} ParolePlayerClass;
+
+GType        			 parole_player_get_type        (void) G_GNUC_CONST;
+ParolePlayer       		*parole_player_new             (void);
+
+ParoleMediaList			*parole_player_get_media_list  (ParolePlayer *player);
+
+G_END_DECLS
+
+#endif /* __PAROLE_PLAYER_H */

Added: parole/trunk/parole/parole-plugin.c
===================================================================
--- parole/trunk/parole/parole-plugin.c	                        (rev 0)
+++ parole/trunk/parole/parole-plugin.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,468 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 "parole-plugin.h"
+#include "parole-medialist.h"
+#include "parole-plugins-manager.h"
+#include "parole-gst.h"
+#include "gmarshal.h"
+#include "enum-gtypes.h"
+
+static void parole_plugin_finalize     (GObject *object);
+
+static void parole_plugin_set_property (GObject *object,
+				        guint prop_id,
+				        const GValue *value,
+					GParamSpec *pspec);
+			     
+static void parole_plugin_get_property (GObject *object,
+					guint prop_id,
+					GValue *value,
+					GParamSpec *pspec);
+
+#define PAROLE_PLUGIN_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_PLUGIN, ParolePluginPrivate))
+
+typedef struct _ParolePluginPrivate ParolePluginPrivate;
+
+struct _ParolePluginPrivate
+{
+    ParoleGst *gst;
+    
+    gchar *title;
+    gchar *author;
+    gchar *desc;
+    
+    gboolean packed;
+    
+    
+    /* sig id's*/
+    gulong gst_sig1;
+    gulong gst_sig2;
+};
+
+enum
+{
+    PROP_0,
+    PROP_TITLE,
+    PROP_DESC,
+    PROP_AUTHOR
+};
+
+enum
+{
+    STATE_CHANGED,
+    TAG_MESSAGE,
+    FREE_DATA,
+    LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (ParolePlugin, parole_plugin, G_TYPE_OBJECT)
+
+static void 
+parole_plugin_media_state_changed_cb (ParoleGst *gst, const ParoleStream *stream, 
+				      ParoleMediaState state, ParolePlugin *plugin)
+{
+    g_signal_emit (G_OBJECT (plugin), signals [STATE_CHANGED], 0, stream, state);
+}
+
+static void 
+parole_plugin_media_tag_cb (ParoleGst *gst, const ParoleStream *stream, ParolePlugin *plugin)
+{
+    g_signal_emit (G_OBJECT (plugin), signals [TAG_MESSAGE], 0, stream);
+}
+
+static void
+parole_plugin_class_init (ParolePluginClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_plugin_finalize;
+
+    object_class->get_property = parole_plugin_get_property;
+    object_class->set_property = parole_plugin_set_property;
+
+    /**
+     * ParolePlugin::state-changed:
+     * @plugin: the object which received the signal.
+     * @stream: a #ParoleStream.
+     * @state: the new state.
+     * 
+     * Since: 0.1 
+     **/
+    signals[STATE_CHANGED] = 
+        g_signal_new ("state-changed",
+                      PAROLE_TYPE_PLUGIN,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParolePluginClass, state_changed),
+                      NULL, NULL,
+                      _gmarshal_VOID__OBJECT_ENUM,
+                      G_TYPE_NONE, 2,
+		      PAROLE_TYPE_STREAM, ENUM_GTYPE_STATE);
+
+    /**
+     * ParolePlugin::tag-message:
+     * @plugin: the object which received the signal.
+     * @stream: a #ParoleStream.
+     * 
+     * Since: 0.1 
+     **/
+    signals[TAG_MESSAGE] = 
+        g_signal_new ("tag-message",
+                      PAROLE_TYPE_PLUGIN,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParolePluginClass, tag_message),
+                      NULL, NULL,
+		      g_cclosure_marshal_VOID__OBJECT,
+                      G_TYPE_NONE, 1, PAROLE_TYPE_STREAM);
+
+    /**
+     * ParolePlugin::free-data:
+     * @plugin: the object which received the signal.
+     * 
+     * Emitted before unloading the plugin from memory, so
+     * any dynamiclly allocated memory should be freed in this signal
+     * handler.
+     * 
+     * Since: 0.1 
+     **/
+    signals [FREE_DATA] = 
+        g_signal_new ("free-data",
+                      PAROLE_TYPE_PLUGIN,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET(ParolePluginClass, free_data),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0, G_TYPE_NONE);
+
+    /**
+     * ParolePlugin:title:
+     * 
+     * Title to display for this plugin.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+                                     PROP_TITLE,
+                                     g_param_spec_string ("title",
+                                                          NULL, NULL,
+                                                          NULL,
+                                                          G_PARAM_READWRITE|
+							  G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * ParolePlugin:desc:
+     * 
+     * Description of the plugin.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+                                     PROP_DESC,
+                                     g_param_spec_string ("desc",
+                                                          NULL, NULL,
+                                                          NULL,
+                                                          G_PARAM_READWRITE|
+							  G_PARAM_CONSTRUCT_ONLY));
+
+    /**
+     * ParolePlugin:author:
+     * 
+     * Author of the plugin.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+                                     PROP_AUTHOR,
+                                     g_param_spec_string ("author",
+                                                          NULL, NULL,
+                                                          NULL,
+                                                          G_PARAM_READWRITE|
+							  G_PARAM_CONSTRUCT_ONLY));
+							  
+    g_type_class_add_private (klass, sizeof (ParolePluginPrivate));
+}
+
+static void
+parole_plugin_init (ParolePlugin *plugin)
+{
+    ParolePluginPrivate *priv;
+    
+    priv = PAROLE_PLUGIN_GET_PRIVATE (plugin);
+    
+    priv->title  = NULL;
+    priv->packed = FALSE;
+    
+    priv->gst = PAROLE_GST (parole_gst_new ());
+    
+    priv->gst_sig1 = g_signal_connect (G_OBJECT (priv->gst), "media-state",
+				       G_CALLBACK (parole_plugin_media_state_changed_cb), plugin);
+		      
+    priv->gst_sig2 = g_signal_connect (G_OBJECT (priv->gst), "media-tag",
+				       G_CALLBACK (parole_plugin_media_tag_cb), plugin);
+}
+
+static void parole_plugin_set_property (GObject *object,
+					guint prop_id,
+				        const GValue *value,
+					GParamSpec *pspec)
+{
+    ParolePlugin *plugin;
+    plugin = PAROLE_PLUGIN (object);
+
+    switch (prop_id)
+    {
+	case PROP_TITLE:
+	    PAROLE_PLUGIN_GET_PRIVATE (plugin)->title = g_value_dup_string (value);
+	    break;
+	case PROP_DESC:
+	    PAROLE_PLUGIN_GET_PRIVATE (plugin)->desc = g_value_dup_string (value);
+	    break;
+	case PROP_AUTHOR:
+	    PAROLE_PLUGIN_GET_PRIVATE (plugin)->author = g_value_dup_string (value);
+	    break;
+	default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void parole_plugin_get_property (GObject *object,
+					guint prop_id,
+					GValue *value,
+	
+					GParamSpec *pspec)
+{
+    ParolePlugin *plugin;
+    plugin = PAROLE_PLUGIN (object);
+
+    switch (prop_id)
+    {
+	case PROP_TITLE:
+	    g_value_set_string (value, PAROLE_PLUGIN_GET_PRIVATE (plugin)->title);
+	    break;
+	case PROP_DESC:
+	    g_value_set_string (value, PAROLE_PLUGIN_GET_PRIVATE (plugin)->desc);
+	    break;
+	case PROP_AUTHOR:
+	    g_value_set_string (value, PAROLE_PLUGIN_GET_PRIVATE (plugin)->author);
+	    break;
+	default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+parole_plugin_finalize (GObject *object)
+{
+    ParolePlugin *plugin;
+    ParolePluginPrivate *priv;
+
+    plugin = PAROLE_PLUGIN (object);
+    
+    priv = PAROLE_PLUGIN_GET_PRIVATE (plugin);
+    
+    if ( G_IS_OBJECT (priv->gst) )
+    {
+	if (g_signal_handler_is_connected (priv->gst, priv->gst_sig1)) 
+	    g_signal_handler_disconnect (priv->gst, priv->gst_sig1);
+
+	if ( g_signal_handler_is_connected (priv->gst, priv->gst_sig2)) 
+	g_signal_handler_disconnect (priv->gst, priv->gst_sig2);
+    }
+    
+    if ( priv->title )
+	g_free (priv->title);
+
+    G_OBJECT_CLASS (parole_plugin_parent_class)->finalize (object);
+}
+
+
+/**
+ * parole_plugin_new:
+ * @title: title.
+ * 
+ * 
+ * 
+ * Returns: A new #ParolePlugin object.
+ **/
+ParolePlugin *
+parole_plugin_new (const gchar *title, const gchar *desc, const gchar *author)
+{
+    ParolePlugin *plugin = NULL;
+    
+    plugin = g_object_new (PAROLE_TYPE_PLUGIN, 
+			   "title", title, 
+			   "desc", desc,
+			   "author", author,
+			   NULL);
+    return plugin;
+}
+
+/**
+ * parole_plugin_get_main_window:
+ * @plugin: a #ParolePlugin.
+ * 
+ * Get the main window of the media player.
+ * 
+ * Returns: the main window widget.
+ **/
+GtkWidget *parole_plugin_get_main_window (ParolePlugin *plugin)
+{
+    
+    
+    return NULL;
+}
+
+/**
+ * parole_plugin_pack_widget:
+ * @plugin: a #ParolePlugin.
+ * @widget: a #GtkWidget.
+ * @container: a ParolePluginContainer type.
+ * 
+ * This function inserts a tab containing the @widget, the tab can be either
+ * on the playlist when PAROLE_PLUGIN_CONTAINER_PLAYLIST is specified or in the 
+ * main view when PAROLE_PLUGIN_CONTAINER_VIEW is specified.
+ *
+ * 
+ * Note: You can call this function only one time.
+ **/
+void parole_plugin_pack_widget (ParolePlugin *plugin, GtkWidget *widget, ParolePluginContainer container)
+{
+    ParolePluginsManager *manager;
+    ParolePluginPrivate *priv;
+    
+    g_return_if_fail (PAROLE_IS_PLUGIN (plugin));
+    
+    priv = PAROLE_PLUGIN_GET_PRIVATE (plugin);
+    
+    g_return_if_fail (priv->packed == FALSE);
+    
+    manager = parole_plugins_manager_new ();
+
+    parole_plugins_manager_pack (manager, plugin, widget, container);
+
+    g_object_unref (manager);
+    
+    priv->packed = TRUE;
+}
+
+/**
+ * parole_plugin_play_uri:
+ * @plugin: a #ParolePlugin.
+ * @uri: uri of the file to play.
+ * 
+ * Play a uri.
+ * 
+ * Returns: TRUE on success, FALSE otherwise.
+ **/
+gboolean parole_plugin_play_uri (ParolePlugin *plugin, const gchar *uri)
+{
+    
+    
+    return TRUE;
+}
+
+/**
+ * parole_plugin_play_file:
+ * @plugin: a #ParolePlugin.
+ * @file: a #ParoleMefiaFile to play.
+ * 
+ * Play a #ParoleMediaFile.
+ * 
+ * Returns: TRUE on success, FALSE otherwise.
+ **/
+gboolean parole_plugin_play_file (ParolePlugin *plugin, ParoleMediaFile *file)
+{
+    
+    
+    
+    return TRUE;
+}
+
+/**
+ * parole_plugin_pause_playing:
+ * @plugin: a #ParolePlugin.
+ * 
+ * Causes the media player to pause any playback.
+ * 
+ * Returns: TRUE on success, FALSE otherwise.
+ **/
+gboolean parole_plugin_pause_playing (ParolePlugin *plugin)
+{
+    
+    return TRUE;
+}
+
+/**
+ * parole_plugin_pause_playing:
+ * @plugin: a #ParolePlugin.
+ * 
+ * Causes the media player to resume playing the currently paused stream.
+ * 
+ * Returns: TRUE on success, FALSE otherwise.
+ **/
+gboolean  parole_plugin_resume (ParolePlugin *plugin)
+{
+    
+    
+    return TRUE;
+}
+	
+/**
+ * parole_plugin_stop_playing:
+ * @plugin: a #ParolePlugin.
+ * 
+ * Causes the media player to stop any playback.
+ * 
+ * Returns: TRUE on success, FALSE otherwise.
+ **/
+gboolean parole_plugin_stop_playing (ParolePlugin *plugin)
+{
+    
+    return TRUE;
+}
+
+/**
+ * parole_plugin_seek:
+ * @plugin: a #ParolePlugin.
+ * @pos: position.
+ * 
+ * Seek the current playing stream.
+ * 
+ * Returns: False is the stream is not seekable or an error occurs, TRUE otherwise.
+ **/
+gboolean parole_plugin_seek (ParolePlugin *plugin, gdouble pos)
+{
+    
+    
+    return TRUE;
+}

Added: parole/trunk/parole/parole-plugin.h
===================================================================
--- parole/trunk/parole/parole-plugin.h	                        (rev 0)
+++ parole/trunk/parole/parole-plugin.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,104 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_PLUGIN_H
+#define __PAROLE_PLUGIN_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+#include <parole/parole-stream.h>
+#include <parole/parole-mediafile.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_PLUGIN        (parole_plugin_get_type () )
+#define PAROLE_PLUGIN(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_PLUGIN, ParolePlugin))
+#define PAROLE_IS_PLUGIN(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_PLUGIN))
+
+typedef struct _ParolePlugin 	    ParolePlugin;
+typedef struct _ParolePluginClass   ParolePluginClass;
+
+typedef enum
+{
+    PAROLE_PLUGIN_CONTAINER_PLAYLIST,
+    PAROLE_PLUGIN_CONTAINER_VIEW
+} ParolePluginContainer;
+
+
+typedef enum
+{
+    
+    PAROLE_STATE_STOPPED,
+    PAROLE_STATE_PLAYBACK_FINISHED,
+    PAROLE_STATE_PAUSED,
+    PAROLE_STATE_PLAYING
+    
+} ParoleState;
+
+struct _ParolePlugin
+{
+    GObject       	     parent;
+};
+
+struct _ParolePluginClass
+{
+    GObjectClass 	     parent_class;
+    
+    void		    (*state_changed)		   (ParolePlugin *plugin,
+						            const ParoleStream *stream,
+							    ParoleState state);
+    
+    void		    (*tag_message)                 (ParolePlugin *plugin,
+							    const ParoleStream *stream);
+    
+    void		    (*free_data)		   (ParolePlugin *plugin);
+};
+
+GType        		     parole_plugin_get_type        (void) G_GNUC_CONST;
+
+ParolePlugin       	    *parole_plugin_new             (const gchar *title,
+							    const gchar *desc, 
+							    const gchar *author);
+
+GtkWidget		    *parole_plugin_get_main_window (ParolePlugin *plugin);
+
+void			     parole_plugin_pack_widget	   (ParolePlugin *plugin,
+							    GtkWidget *widget,
+							    ParolePluginContainer container);
+
+gboolean		     parole_plugin_play_uri        (ParolePlugin *plugin,
+							    const gchar *uri);
+
+gboolean		     parole_plugin_play_file       (ParolePlugin *plugin,
+							    ParoleMediaFile *file);
+							    
+gboolean		     parole_plugin_pause_playing   (ParolePlugin *plugin);
+
+gboolean		     parole_plugin_resume          (ParolePlugin *plugin);
+							    
+gboolean		     parole_plugin_stop_playing    (ParolePlugin *plugin);
+
+gboolean		     parole_plugin_seek            (ParolePlugin *plugin,
+						            gdouble pos);
+
+G_END_DECLS
+
+#endif /* __PAROLE_PLUGIN_H */

Added: parole/trunk/parole/parole-plugins-manager.c
===================================================================
--- parole/trunk/parole/parole-plugins-manager.c	                        (rev 0)
+++ parole/trunk/parole/parole-plugins-manager.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,201 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <glib.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include "common/parole-builder.h"
+
+#include "parole-plugins-manager.h"
+#include "parole-module.h"
+
+static void parole_plugins_manager_finalize   (GObject *object);
+
+#define PAROLE_PLUGINS_MANAGER_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_PLUGINS_MANAGER, ParolePluginsManagerPrivate))
+
+struct ParolePluginsManagerPrivate
+{
+    GtkWidget *list_nt;
+    GtkWidget *view_nt;
+    
+    GPtrArray *array;
+};
+
+G_DEFINE_TYPE (ParolePluginsManager, parole_plugins_manager, G_TYPE_OBJECT)
+
+static void
+parole_plugins_manager_unload_all (gpointer data, gpointer user_data)
+{
+    
+    ParoleModule *module;
+    
+    module = PAROLE_MODULE (data);
+    
+    g_type_module_unuse (G_TYPE_MODULE (data));
+    g_object_unref (G_OBJECT (module));
+}
+
+static void
+parole_plugins_manager_show_plugins_pref (GtkWidget *widget, ParolePluginsManager *manager)
+{
+    
+}
+
+static void
+parole_plugins_manager_class_init (ParolePluginsManagerClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_plugins_manager_finalize;
+
+    g_type_class_add_private (klass, sizeof (ParolePluginsManagerPrivate));
+}
+
+static void
+parole_plugins_manager_init (ParolePluginsManager *manager)
+{
+    ParolePlugin *plugin;
+    GtkBuilder *builder;
+    
+    manager->priv = PAROLE_PLUGINS_MANAGER_GET_PRIVATE (manager);
+    
+    manager->priv->array = g_ptr_array_new ();
+    
+    builder = parole_builder_get_main_interface ();
+    manager->priv->list_nt = GTK_WIDGET (gtk_builder_get_object (builder, "notebook-playlist"));
+    
+    g_signal_connect (gtk_builder_get_object (builder, "plugins-menu-item"), "activate",
+		      G_CALLBACK (parole_plugins_manager_show_plugins_pref), manager);
+		     
+    g_object_unref (builder);
+    
+    plugin = parole_plugin_new (NULL, NULL, NULL);
+    g_object_unref (plugin);
+}
+
+static void
+parole_plugins_manager_finalize (GObject *object)
+{
+    ParolePluginsManager *manager;
+
+    manager = PAROLE_PLUGINS_MANAGER (object);
+    
+    g_ptr_array_foreach (manager->priv->array, 
+		        (GFunc)parole_plugins_manager_unload_all, NULL);
+    g_ptr_array_free (manager->priv->array, TRUE);
+
+    G_OBJECT_CLASS (parole_plugins_manager_parent_class)->finalize (object);
+}
+
+static void
+parole_plugins_manager_add (ParolePluginsManager *manager, const gchar *filename)
+{
+    ParoleModule *module;
+    
+    module = parole_module_new (filename);
+    
+    if ( g_type_module_use (G_TYPE_MODULE (module)) )
+	g_ptr_array_add (manager->priv->array, module);
+    else
+	g_object_unref (module);
+    
+}
+
+ParolePluginsManager *
+parole_plugins_manager_new (void)
+{
+    static gpointer parole_plugins_manager_object = NULL;
+    
+    if ( G_LIKELY (parole_plugins_manager_object != NULL) )
+    {
+	g_object_ref (parole_plugins_manager_object);
+    }
+    else
+    {
+	parole_plugins_manager_object = g_object_new (PAROLE_TYPE_PLUGINS_MANAGER, NULL);
+	g_object_add_weak_pointer (parole_plugins_manager_object, &parole_plugins_manager_object);
+    }
+    
+    return PAROLE_PLUGINS_MANAGER (parole_plugins_manager_object);
+}
+
+void parole_plugins_manager_load_plugins	(ParolePluginsManager *manager)
+{
+    GDir *dir;
+    const gchar *name;
+    gchar *path;
+    GError *error = NULL;
+    
+    dir = g_dir_open (PAROLE_PLUGINS_DIR, 0, &error);
+    
+    if ( error )
+    {
+	g_critical ("Error opening plugins dir: %s", error->message);
+	g_error_free (error);
+	return;
+    }
+    
+    while ( (name = g_dir_read_name (dir) ))
+    {
+	if ( g_str_has_suffix (name, "." G_MODULE_SUFFIX) )
+	{
+	    path = g_build_filename (PAROLE_PLUGINS_DIR, name, NULL);
+	    TRACE ("loading module with path %s", path);
+	    parole_plugins_manager_add (manager, path);
+	    g_free (path);
+	}
+    }
+    
+    g_dir_close (dir);
+}
+
+void parole_plugins_manager_pack (ParolePluginsManager *manager, ParolePlugin *plugin,
+				  GtkWidget *widget, ParolePluginContainer container)
+{
+    gchar *title;
+    
+    g_object_get (G_OBJECT (plugin),
+		  "title", &title,
+		  NULL);
+    
+    if ( container == PAROLE_PLUGIN_CONTAINER_PLAYLIST )
+    {
+	gtk_notebook_append_page (GTK_NOTEBOOK (manager->priv->list_nt), widget, gtk_label_new (title));
+	gtk_widget_show_all (widget);
+    }
+    else if ( container == PAROLE_PLUGIN_CONTAINER_VIEW )
+    {
+	
+    }
+    
+    if ( title )
+	g_free (title);
+	
+}

Added: parole/trunk/parole/parole-plugins-manager.h
===================================================================
--- parole/trunk/parole/parole-plugins-manager.h	                        (rev 0)
+++ parole/trunk/parole/parole-plugins-manager.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,61 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_PLUGINS_MANAGER_H
+#define __PAROLE_PLUGINS_MANAGER_H
+
+#include <glib-object.h>
+#include "parole-plugin.h"
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_PLUGINS_MANAGER        (parole_plugins_manager_get_type () )
+#define PAROLE_PLUGINS_MANAGER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_PLUGINS_MANAGER, ParolePluginsManager))
+#define PAROLE_IS_PLUGINS_MANAGER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_PLUGINS_MANAGER))
+
+typedef struct ParolePluginsManagerPrivate ParolePluginsManagerPrivate;
+
+typedef struct
+{
+    GObject         		     parent;
+    ParolePluginsManagerPrivate     *priv;
+    
+} ParolePluginsManager;
+
+typedef struct
+{
+    GObjectClass 		    parent_class;
+    
+} ParolePluginsManagerClass;
+
+GType        			    parole_plugins_manager_get_type       (void) G_GNUC_CONST;
+
+ParolePluginsManager               *parole_plugins_manager_new            (void);
+
+void				    parole_plugins_manager_load_plugins	  (ParolePluginsManager *manager);
+
+void				    parole_plugins_manager_pack		  (ParolePluginsManager *manager,
+									   ParolePlugin *plugin,
+									   GtkWidget *widget,
+									   ParolePluginContainer container);
+
+G_END_DECLS
+
+#endif /* __PAROLE_PLUGIN_MANAGER_H */

Added: parole/trunk/parole/parole-rc-utils.c
===================================================================
--- parole/trunk/parole/parole-rc-utils.c	                        (rev 0)
+++ parole/trunk/parole/parole-rc-utils.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,101 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <glib.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include "parole-rc-utils.h"
+
+#define MEDIA_PLAYER_RESOURCE_FILE 	"xfce4/parole/parole-media-player.rc"
+
+static XfceRc *
+open_resource_file (gboolean readonly)
+{
+    gchar *file;
+    XfceRc *rc;
+    file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, MEDIA_PLAYER_RESOURCE_FILE, TRUE);
+    rc = xfce_rc_simple_open (file, readonly);
+    g_free (file);
+    
+    return rc;
+}
+
+void parole_rc_write_entry_bool (const gchar *property, gboolean value)
+{
+    XfceRc *rc = open_resource_file (FALSE);
+    
+    xfce_rc_write_bool_entry (rc, property, value);
+    xfce_rc_close (rc);
+}
+
+void parole_rc_write_entry_int (const gchar *property, gint value)
+{
+    XfceRc *rc = open_resource_file (FALSE);
+    
+    xfce_rc_write_int_entry (rc, property, value);
+    xfce_rc_close (rc);
+}
+
+void parole_rc_write_entry_string	(const gchar *property, const gchar *value)
+{
+    XfceRc *rc = open_resource_file (FALSE);
+    
+    xfce_rc_write_entry (rc, property, value);
+    xfce_rc_close (rc);
+}
+
+gboolean parole_rc_read_entry_bool (const gchar *property, gboolean fallback)
+{
+    XfceRc *rc = open_resource_file (TRUE);
+    
+    if ( rc )
+	return xfce_rc_read_bool_entry (rc, property, fallback);
+	
+    return fallback;
+}
+
+gint parole_rc_read_entry_int (const gchar *property, gint fallback)
+{
+    XfceRc *rc = open_resource_file (TRUE);
+    
+    if ( rc )
+	return xfce_rc_read_int_entry (rc, property, fallback);
+	
+    return fallback;
+}
+
+const gchar *parole_rc_read_entry_string (const gchar *property, const gchar *fallback)
+{
+    XfceRc *rc = open_resource_file (TRUE);
+    
+    if ( rc )
+        return xfce_rc_read_entry (rc, property, fallback);
+	
+    return fallback;
+}

Added: parole/trunk/parole/parole-rc-utils.h
===================================================================
--- parole/trunk/parole/parole-rc-utils.h	                        (rev 0)
+++ parole/trunk/parole/parole-rc-utils.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,43 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __RC_UTILS_
+#define __RC_UTILS_
+
+void			parole_rc_write_entry_bool	(const gchar *property,
+							 gboolean value);
+
+void			parole_rc_write_entry_int	(const gchar *property,
+							 gint value);
+							 
+void 			parole_rc_write_entry_string	(const gchar *property, 
+							 const gchar *value);
+							 
+gboolean 		parole_rc_read_entry_bool	(const gchar *property,
+							 gboolean fallback);
+
+gint			parole_rc_read_entry_int	(const gchar *property,
+							 gint fallback);
+
+const gchar	       *parole_rc_read_entry_string	(const gchar *property,
+							 const gchar *fallback);
+
+
+#endif /* __RC_UTILS_ */

Added: parole/trunk/parole/parole-screensaver.c
===================================================================
--- parole/trunk/parole/parole-screensaver.c	                        (rev 0)
+++ parole/trunk/parole/parole-screensaver.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,107 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <X11/Xlib.h>
+
+#include <gdk/gdkx.h>
+
+#include "parole-screensaver.h"
+
+#define RESET_SCREENSAVER_TIMEOUT	6
+
+#define PAROLE_SCREEN_SAVER_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_SCREENSAVER, ParoleScreenSaverPrivate))
+
+struct ParoleScreenSaverPrivate
+{
+    gulong reset_id;
+};
+
+G_DEFINE_TYPE (ParoleScreenSaver, parole_screen_saver, G_TYPE_OBJECT)
+
+
+static void
+parole_screen_saver_finalize (GObject *object)
+{
+    ParoleScreenSaver *saver;
+
+    saver = PAROLE_SCREEN_SAVER (object);
+
+    G_OBJECT_CLASS (parole_screen_saver_parent_class)->finalize (object);
+}
+
+static void
+parole_screen_saver_class_init (ParoleScreenSaverClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_screen_saver_finalize;
+
+    g_type_class_add_private (klass, sizeof (ParoleScreenSaverPrivate));
+}
+
+static void
+parole_screen_saver_init (ParoleScreenSaver *saver)
+{
+    saver->priv = PAROLE_SCREEN_SAVER_GET_PRIVATE (saver);
+    
+    saver->priv->reset_id = 0;
+}
+
+static gboolean
+parole_screen_saver_reset_timeout (gpointer data)
+{
+    XResetScreenSaver (GDK_DISPLAY ());
+    return TRUE;
+}
+
+ParoleScreenSaver *
+parole_screen_saver_new (void)
+{
+    ParoleScreenSaver *saver = NULL;
+    saver = g_object_new (PAROLE_TYPE_SCREENSAVER, NULL);
+    return saver;
+}
+
+void parole_screen_saver_inhibit (ParoleScreenSaver *saver)
+{
+    parole_screen_saver_uninhibit (saver);
+	
+    saver->priv->reset_id = g_timeout_add_seconds (RESET_SCREENSAVER_TIMEOUT, 
+						   (GSourceFunc) parole_screen_saver_reset_timeout,
+						   NULL);
+}
+
+void parole_screen_saver_uninhibit (ParoleScreenSaver *saver)
+{
+    if ( saver->priv->reset_id != 0 )
+    {
+	g_source_remove (saver->priv->reset_id);
+	saver->priv->reset_id = 0;
+    }
+}

Added: parole/trunk/parole/parole-screensaver.h
===================================================================
--- parole/trunk/parole/parole-screensaver.h	                        (rev 0)
+++ parole/trunk/parole/parole-screensaver.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,56 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_SCREEN_SAVER_H
+#define __PAROLE_SCREEN_SAVER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_SCREENSAVER        (parole_screen_saver_get_type () )
+#define PAROLE_SCREEN_SAVER(o)         (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_SCREENSAVER, ParoleScreenSaver))
+#define PAROLE_IS_SCREENSAVER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_SCREENSAVER))
+
+typedef struct ParoleScreenSaverPrivate ParoleScreenSaverPrivate;
+
+typedef struct
+{
+    GObject         		  parent;
+    ParoleScreenSaverPrivate     *priv;
+    
+} ParoleScreenSaver;
+
+typedef struct
+{
+    GObjectClass 		  parent_class;
+    
+} ParoleScreenSaverClass;
+
+GType        			  parole_screen_saver_get_type        (void) G_GNUC_CONST;
+ParoleScreenSaver       	 *parole_screen_saver_new             (void);
+
+void				  parole_screen_saver_inhibit	      (ParoleScreenSaver *saver);
+
+void				  parole_screen_saver_uninhibit	      (ParoleScreenSaver *saver);
+
+G_END_DECLS
+
+#endif /* __PAROLE_SCREEN_SAVER_H */

Added: parole/trunk/parole/parole-sidebar.c
===================================================================
--- parole/trunk/parole/parole-sidebar.c	                        (rev 0)
+++ parole/trunk/parole/parole-sidebar.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,197 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <gtk/gtk.h>
+#include <glib.h>
+
+#include <libxfce4util/libxfce4util.h>
+#include <libxfcegui4/libxfcegui4.h>
+
+#include "common/parole-builder.h"
+
+#include "parole-sidebar.h"
+
+#define PAROLE_SIDEBAR_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_SIDEBAR, ParoleSidebarPrivate))
+
+struct ParoleSidebarPrivate
+{
+    GtkWidget	*treeview;
+    GtkWidget   *nt;
+    
+    gboolean	 visible;
+};
+
+enum
+{
+    PIXBUF_COL,
+    NAME_COL,
+    NOTEBOOK_NUMBER,
+    COL_NUMBERS
+};
+
+G_DEFINE_TYPE (ParoleSidebar, parole_sidebar, G_TYPE_OBJECT)
+
+static void
+parole_sidebar_finalize (GObject *object)
+{
+    ParoleSidebar *sidebar;
+
+    sidebar = PAROLE_SIDEBAR (object);
+
+    G_OBJECT_CLASS (parole_sidebar_parent_class)->finalize (object);
+}
+
+static void
+parole_sidebar_class_init (ParoleSidebarClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_sidebar_finalize;
+
+    g_type_class_add_private (klass, sizeof (ParoleSidebarPrivate));
+}
+
+static void
+parole_sidebar_cursor_changed_cb (ParoleSidebar *sidebar)
+{
+    GtkTreeSelection *sel;
+    GtkTreeModel     *model;
+    GtkTreeIter       iter;
+    gint int_data = 0;
+    
+    sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidebar->priv->treeview));
+
+    if ( !gtk_tree_selection_get_selected (sel, &model, &iter))
+	return;
+
+    gtk_tree_model_get (model,
+                        &iter,
+                        NOTEBOOK_NUMBER,
+                        &int_data,
+                        -1);
+
+    gtk_notebook_set_current_page (GTK_NOTEBOOK (sidebar->priv->nt), int_data);
+}
+
+static void
+parole_sidebar_setup (ParoleSidebar *sidebar)
+{
+    GtkListStore *list_store;
+    GtkTreeViewColumn *col;
+    GtkCellRenderer *renderer;
+    GtkTreeSelection *sel;
+    GtkTreePath *path;
+    GtkTreeIter iter;
+    GdkPixbuf *pix;
+    guint i = 0;
+    
+    list_store = gtk_list_store_new (COL_NUMBERS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT);
+
+    gtk_tree_view_set_model (GTK_TREE_VIEW (sidebar->priv->treeview), GTK_TREE_MODEL(list_store));
+    
+    gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (sidebar->priv->treeview), TRUE);
+    col = gtk_tree_view_column_new ();
+
+    renderer = gtk_cell_renderer_pixbuf_new ();
+    
+    gtk_tree_view_column_pack_start(col, renderer, FALSE);
+    gtk_tree_view_column_set_attributes(col, renderer, "pixbuf", PIXBUF_COL, NULL);
+
+    renderer = gtk_cell_renderer_text_new();
+    
+    gtk_tree_view_column_pack_start (col, renderer, FALSE);
+    gtk_tree_view_column_set_attributes (col, renderer, "markup", NAME_COL, NULL);
+    
+    gtk_tree_view_append_column (GTK_TREE_VIEW (sidebar->priv->treeview), col);
+    
+    /*
+     * Multimedia tab
+     */
+    pix = xfce_themed_icon_load ("multimedia", 24);
+    gtk_list_store_append (list_store, &iter);
+    gtk_list_store_set (list_store, &iter, PIXBUF_COL, pix, NAME_COL, _("<b>Media \nplayer\n</b>"), NOTEBOOK_NUMBER, i, -1);
+    i++;
+    if ( pix )
+	g_object_unref (pix);
+	
+    /*
+     * Album
+     */
+    pix = xfce_themed_icon_load ("", 24);
+    gtk_list_store_append (list_store, &iter);
+    gtk_list_store_set (list_store, &iter, PIXBUF_COL, pix, NAME_COL, _("<b>Albums\n</b>"), NOTEBOOK_NUMBER, i, -1);
+    i++;
+    if ( pix )
+	g_object_unref (pix);
+	
+    g_signal_connect_swapped (G_OBJECT (sidebar->priv->treeview), "cursor_changed",
+			      G_CALLBACK (parole_sidebar_cursor_changed_cb), sidebar);
+    
+    sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidebar->priv->treeview));
+    path = gtk_tree_path_new_first ();
+    gtk_tree_selection_select_path (sel, path);
+    gtk_tree_path_free (path);
+}
+
+static void
+parole_sidebar_init (ParoleSidebar *sidebar)
+{
+    GtkBuilder *builder;
+    
+    sidebar->priv = PAROLE_SIDEBAR_GET_PRIVATE (sidebar);
+    
+    builder = parole_builder_get_main_interface ();
+    
+    sidebar->priv->visible = TRUE;
+    sidebar->priv->treeview = GTK_WIDGET (gtk_builder_get_object (builder, "treeview"));
+    sidebar->priv->nt = GTK_WIDGET (gtk_builder_get_object (builder, "notebook"));
+    
+    parole_sidebar_setup (sidebar);
+    
+    g_object_unref (builder);
+}
+
+ParoleSidebar *
+parole_sidebar_new (void)
+{
+    ParoleSidebar *sidebar = NULL;
+    sidebar = g_object_new (PAROLE_TYPE_SIDEBAR, NULL);
+    return sidebar;
+}
+
+void parole_sidebar_set_visible (ParoleSidebar *sidebar, gboolean visible)
+{
+    if ( visible )
+    {
+	if ( sidebar->priv->visible )
+	    gtk_widget_show_all (sidebar->priv->treeview);
+    }
+    else
+	gtk_widget_hide_all (sidebar->priv->treeview);
+}

Added: parole/trunk/parole/parole-sidebar.h
===================================================================
--- parole/trunk/parole/parole-sidebar.h	                        (rev 0)
+++ parole/trunk/parole/parole-sidebar.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,55 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_SIDEBAR_H
+#define __PAROLE_SIDEBAR_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_SIDEBAR        (parole_sidebar_get_type () )
+#define PAROLE_SIDEBAR(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_SIDEBAR, ParoleSidebar))
+#define PAROLE_IS_SIDEBAR(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_SIDEBAR))
+
+typedef struct ParoleSidebarPrivate ParoleSidebarPrivate;
+
+typedef struct
+{
+    GObject         	 	parent;
+    ParoleSidebarPrivate       *priv;
+    
+} ParoleSidebar;
+
+typedef struct
+{
+    GObjectClass 	 	parent_class;
+    
+} ParoleSidebarClass;
+
+GType        		 	parole_sidebar_get_type        (void) G_GNUC_CONST;
+ParoleSidebar       	       *parole_sidebar_new             (void);
+
+void				parole_sidebar_set_visible     (ParoleSidebar *sidebar,
+							        gboolean visible);
+
+G_END_DECLS
+
+#endif /* __PAROLE_SIDEBAR_H */

Added: parole/trunk/parole/parole-statusbar.c
===================================================================
--- parole/trunk/parole/parole-statusbar.c	                        (rev 0)
+++ parole/trunk/parole/parole-statusbar.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,150 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <gtk/gtk.h>
+
+#include <libxfcegui4/libxfcegui4.h>
+
+#include "common/parole-builder.h"
+
+#include "parole-statusbar.h"
+
+#define PAROLE_STATUSBAR_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_STATUSBAR, ParoleStatusbarPrivate))
+
+struct ParoleStatusbarPrivate
+{
+    GtkWidget *box;
+    GtkWidget *progress;
+    GtkWidget *label;
+    
+    gdouble    duration;
+};
+
+G_DEFINE_TYPE (ParoleStatusbar, parole_statusbar, G_TYPE_OBJECT)
+
+static void
+parole_statusbar_finalize (GObject *object)
+{
+    ParoleStatusbar *statusbar;
+
+    statusbar = PAROLE_STATUSBAR (object);
+
+    G_OBJECT_CLASS (parole_statusbar_parent_class)->finalize (object);
+}
+
+static void
+parole_statusbar_class_init (ParoleStatusbarClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_statusbar_finalize;
+
+    g_type_class_add_private (klass, sizeof (ParoleStatusbarPrivate));
+}
+
+static void
+parole_statusbar_init (ParoleStatusbar *statusbar)
+{
+    GtkWidget *box;
+    GtkBuilder *builder;
+    
+    statusbar->priv = PAROLE_STATUSBAR_GET_PRIVATE (statusbar);
+    statusbar->priv->duration = 0;
+    
+    builder = parole_builder_get_main_interface ();
+    
+    box = GTK_WIDGET (gtk_builder_get_object (builder, "statusbox"));
+    
+    statusbar->priv->progress = gtk_progress_bar_new ();
+    gtk_widget_hide (statusbar->priv->progress);
+    statusbar->priv->label = gtk_label_new (NULL);
+
+    gtk_misc_set_alignment (GTK_MISC (statusbar->priv->label), 0.0, 0.5);
+
+    gtk_widget_set_size_request (statusbar->priv->progress, 180, 20);
+
+    gtk_box_pack_start (GTK_BOX (box), statusbar->priv->label, FALSE, FALSE, 0);
+    gtk_box_pack_start (GTK_BOX (box), statusbar->priv->progress, FALSE, FALSE, 0);
+
+    gtk_widget_show (box);
+    gtk_widget_show (statusbar->priv->label);
+    g_object_unref (builder);
+    statusbar->priv->box = box;
+}
+
+ParoleStatusbar *
+parole_statusbar_new (void)
+{
+    ParoleStatusbar *statusbar = NULL;
+    statusbar = g_object_new (PAROLE_TYPE_STATUSBAR, NULL);
+    return statusbar;
+}
+
+void parole_statusbar_set_text (ParoleStatusbar *bar, const gchar *text)
+{
+    gtk_label_set_text (GTK_LABEL (bar->priv->label), text);
+    gtk_widget_show (bar->priv->label);
+    gtk_widget_hide (bar->priv->progress);
+}
+
+void parole_statusbar_set_duration (ParoleStatusbar *bar, gdouble duration)
+{
+    bar->priv->duration = duration;
+}
+
+void parole_statusbar_set_position (ParoleStatusbar *bar, gboolean playing, gdouble position)
+{
+    gchar *text;
+
+    if ( bar->priv->duration != 0)
+	text = g_strdup_printf ("%s %4.2f/%4.2f", playing ? _("Playing") : ("Paused"), position, bar->priv->duration);
+    else
+	text = g_strdup_printf ("%s %4.2f", playing ? _("Playing") : ("Paused"), position);
+	
+    parole_statusbar_set_text (bar, text);
+    g_free (text);
+}
+
+void parole_statusbar_set_buffering (ParoleStatusbar *bar, gint percentage)
+{
+    gchar *buff;
+    
+    buff = g_strdup_printf ("%s %d%%", _("Buffering"), percentage);
+    
+    gtk_progress_bar_set_text (GTK_PROGRESS_BAR (bar->priv->progress), buff);
+    gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (bar->priv->progress), (gdouble) percentage/100);
+    gtk_widget_hide (bar->priv->label);
+    gtk_widget_show (bar->priv->progress);
+    g_free (buff);
+}
+
+void parole_statusbar_set_visible (ParoleStatusbar *bar, gboolean visible)
+{
+    visible ? gtk_widget_show (bar->priv->box) : gtk_widget_hide (bar->priv->box);
+}

Added: parole/trunk/parole/parole-statusbar.h
===================================================================
--- parole/trunk/parole/parole-statusbar.h	                        (rev 0)
+++ parole/trunk/parole/parole-statusbar.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,68 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_STATUSBAR_H
+#define __PAROLE_STATUSBAR_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_STATUSBAR        (parole_statusbar_get_type () )
+#define PAROLE_STATUSBAR(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_STATUSBAR, ParoleStatusbar))
+#define PAROLE_IS_STATUSBAR(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_STATUSBAR))
+
+typedef struct ParoleStatusbarPrivate ParoleStatusbarPrivate;
+
+typedef struct
+{
+    GObject         		parent;
+    ParoleStatusbarPrivate     *priv;
+    
+} ParoleStatusbar;
+
+typedef struct
+{
+    GObjectClass 		parent_class;
+    
+} ParoleStatusbarClass;
+
+GType        			parole_statusbar_get_type        (void) G_GNUC_CONST;
+ParoleStatusbar       	       *parole_statusbar_new             (void);
+
+void				parole_statusbar_set_text	 (ParoleStatusbar *bar,
+								  const gchar *text);
+
+void				parole_statusbar_set_duration    (ParoleStatusbar *bar,
+								  gdouble duration);
+
+void				parole_statusbar_set_position    (ParoleStatusbar *bar,
+							          gboolean playing,
+							          gdouble position);
+							    
+void				parole_statusbar_set_buffering   (ParoleStatusbar *bar,
+								  gint percentage);
+
+void				parole_statusbar_set_visible 	 (ParoleStatusbar *bar,
+								  gboolean visible);
+
+G_END_DECLS
+
+#endif /* __PAROLE_STATUSBAR_H */

Added: parole/trunk/parole/parole-stream.c
===================================================================
--- parole/trunk/parole/parole-stream.c	                        (rev 0)
+++ parole/trunk/parole/parole-stream.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,429 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <glib.h>
+
+#include "parole-stream.h"
+#include "parole-mediafile.h"
+
+#define PAROLE_STREAM_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_STREAM, ParoleStreamPrivate))
+
+#define PAROLE_STREAM_FREE_STR_PROP(str)	    \
+    if ( str )					    \
+	g_free (str);				    \
+    str = NULL;					    \
+
+#define PAROLE_STREAM_DUP_GVALUE_STRING(str, value) \
+    PAROLE_STREAM_FREE_STR_PROP (str);		    \
+    str = g_value_dup_string (value);		    \
+
+typedef struct _ParoleStreamPrivate ParoleStreamPrivate;
+
+struct _ParoleStreamPrivate
+{
+    /*Properties*/
+    gpointer 	media_file;
+    
+    gboolean 	has_audio;
+    gboolean    has_video;
+    gboolean 	live;
+    gboolean 	seekable;
+    gdouble   	duration;
+    gint64  	absolute_duration;
+    
+    gchar      *title;
+    gchar      *artist;
+    gchar      *year;
+    gchar      *album;
+    gchar      *comment;
+};
+
+enum
+{
+    PROP_0,
+    PROP_MEDIA_FILE,
+    PROP_LIVE,
+    PROP_HAS_AUDIO,
+    PROP_HAS_VIDEO,
+    PROP_SEEKABLE,
+    PROP_DURATION,
+    PROP_ABSOLUTE_DURATION,
+    PROP_TITLE,
+    PROP_ARTIST,
+    PROP_YEAR,
+    PROP_ALBUM,
+    PROP_COMMENT
+};
+
+G_DEFINE_TYPE (ParoleStream, parole_stream, G_TYPE_OBJECT)
+
+static void parole_stream_set_property (GObject *object,
+				        guint prop_id,
+				        const GValue *value,
+				        GParamSpec *pspec)
+{
+    ParoleStream *stream;
+    stream = PAROLE_STREAM (object);
+
+    switch (prop_id)
+    {
+	case PROP_LIVE:
+	    PAROLE_STREAM_GET_PRIVATE (stream)->live = g_value_get_boolean (value);
+	    break;
+	case PROP_HAS_AUDIO:
+	    PAROLE_STREAM_GET_PRIVATE (stream)->has_audio = g_value_get_boolean (value);
+	    break;
+	case PROP_HAS_VIDEO:
+	    PAROLE_STREAM_GET_PRIVATE (stream)->has_video = g_value_get_boolean (value);
+	    break;
+	case PROP_MEDIA_FILE:
+	    PAROLE_STREAM_GET_PRIVATE (stream)->media_file = g_value_get_object (value);
+	    break;
+	case PROP_SEEKABLE:
+	    PAROLE_STREAM_GET_PRIVATE (stream)->seekable = g_value_get_boolean (value);
+	    break;
+	case PROP_DURATION:
+	    PAROLE_STREAM_GET_PRIVATE (stream)->duration = g_value_get_double (value);
+	    break;
+	case PROP_ABSOLUTE_DURATION:
+	    PAROLE_STREAM_GET_PRIVATE (stream)->absolute_duration = g_value_get_int64 (value);
+	    break;
+	case PROP_TITLE:
+	    PAROLE_STREAM_DUP_GVALUE_STRING (PAROLE_STREAM_GET_PRIVATE (stream)->title, value);
+	    break;
+	case PROP_ARTIST:
+	    PAROLE_STREAM_DUP_GVALUE_STRING (PAROLE_STREAM_GET_PRIVATE (stream)->artist, value);
+	    break;
+	case PROP_YEAR:
+	    PAROLE_STREAM_DUP_GVALUE_STRING (PAROLE_STREAM_GET_PRIVATE (stream)->year, value);
+	    break;
+	case PROP_ALBUM:
+	    PAROLE_STREAM_DUP_GVALUE_STRING (PAROLE_STREAM_GET_PRIVATE (stream)->album, value);
+	    break;
+	case PROP_COMMENT:
+	    PAROLE_STREAM_DUP_GVALUE_STRING (PAROLE_STREAM_GET_PRIVATE (stream)->comment, value);
+	    break;
+	default:
+           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+           break;
+    }
+}
+
+static void parole_stream_get_property (GObject *object,
+				        guint prop_id,
+				        GValue *value,
+				        GParamSpec *pspec)
+{
+    ParoleStream *stream;
+    stream = PAROLE_STREAM (object);
+
+    switch (prop_id)
+    {
+	case PROP_LIVE:
+	    g_value_set_boolean (value, PAROLE_STREAM_GET_PRIVATE (stream)->live);
+	    break;
+	case PROP_HAS_AUDIO:
+	    g_value_set_boolean (value, PAROLE_STREAM_GET_PRIVATE (stream)->has_audio);
+	    break;
+	case PROP_HAS_VIDEO:
+	    g_value_set_boolean (value, PAROLE_STREAM_GET_PRIVATE (stream)->has_video);
+	    break;
+	case PROP_MEDIA_FILE:
+	    g_value_set_object (value, PAROLE_STREAM_GET_PRIVATE (stream)->media_file);
+	    break;
+	case PROP_SEEKABLE:
+	    g_value_set_boolean (value, PAROLE_STREAM_GET_PRIVATE (stream)->seekable);
+	    break;
+	case PROP_DURATION:
+	    g_value_set_double (value, PAROLE_STREAM_GET_PRIVATE (stream)->duration);
+	    break;
+	case PROP_ABSOLUTE_DURATION:
+	    g_value_set_int64 (value, PAROLE_STREAM_GET_PRIVATE (stream)->absolute_duration);
+	    break;
+	case PROP_TITLE:
+	    g_value_set_string (value, PAROLE_STREAM_GET_PRIVATE (stream)->title);
+	    break;
+	case PROP_ARTIST:
+	    g_value_set_string (value, PAROLE_STREAM_GET_PRIVATE (stream)->artist);
+	    break;
+	case PROP_YEAR:
+	    g_value_set_string (value, PAROLE_STREAM_GET_PRIVATE (stream)->year);
+	    break;
+	case PROP_ALBUM:
+	    g_value_set_string (value, PAROLE_STREAM_GET_PRIVATE (stream)->album);
+	    break;
+	case PROP_COMMENT:
+	    g_value_set_string (value, PAROLE_STREAM_GET_PRIVATE (stream)->comment);
+	    break;
+	default:
+	    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	    break;
+    }
+}
+
+static void
+parole_stream_finalize (GObject *object)
+{
+    ParoleStream *stream;
+    ParoleStreamPrivate *priv;
+
+    stream = PAROLE_STREAM (object);
+    priv = PAROLE_STREAM_GET_PRIVATE (stream);
+
+    if ( priv->media_file )
+	g_object_unref (priv->media_file);
+
+    G_OBJECT_CLASS (parole_stream_parent_class)->finalize (object);
+}
+
+static void
+parole_stream_class_init (ParoleStreamClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_stream_finalize;
+
+    object_class->get_property = parole_stream_get_property;
+    object_class->set_property = parole_stream_set_property;
+
+    /**
+     * ParoleStream:media-file:
+     * 
+     * Currently playing #ParoleMediaFile.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_MEDIA_FILE,
+				     g_param_spec_object ("media-file",
+							  NULL, NULL,
+							  PAROLE_TYPE_MEDIA_FILE,
+							  G_PARAM_READWRITE));
+    
+    /**
+     * ParoleStream:has-audio:
+     * 
+     * Whether the stream has audio.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_HAS_AUDIO,
+				     g_param_spec_boolean ("has-audio",
+							   NULL, NULL,
+							   FALSE,
+							   G_PARAM_READWRITE));
+    /**
+     * ParoleStream:has-video:
+     * 
+     * Whether the stream has video.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_HAS_VIDEO,
+				     g_param_spec_boolean ("has-video",
+							   NULL, NULL,
+							   FALSE,
+							   G_PARAM_READWRITE));
+    
+    /**
+     * ParoleStream:live:
+     * 
+     * Whether the stream is a live stream.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_LIVE,
+				     g_param_spec_boolean ("live",
+							   NULL, NULL,
+							   FALSE,
+							   G_PARAM_READWRITE));
+
+    /**
+     * ParoleStream:seekable:
+     * 
+     * Whether the stream is seekable, for example live 
+     * streams are not seekable.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_SEEKABLE,
+				     g_param_spec_boolean ("seekable",
+							   NULL, NULL,
+							   FALSE,
+							   G_PARAM_READWRITE));
+
+    /**
+     * ParoleStream:duration:
+     * 
+     * 
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_DURATION,
+				     g_param_spec_double("duration",
+							 NULL, NULL,
+							 0, G_MAXDOUBLE,
+							 0,
+							 G_PARAM_READWRITE));
+
+    /**
+     * ParoleStream:absolute-duration:
+     * 
+     * 
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_ABSOLUTE_DURATION,
+				     g_param_spec_int64 ("absolute-duration",
+							  NULL, NULL,
+							  0, G_MAXINT64,
+							  0,
+							  G_PARAM_READWRITE));
+
+    /**
+     * ParoleStream:title:
+     * 
+     * 
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_TITLE,
+				     g_param_spec_string ("title",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_READWRITE));
+
+
+    /**
+     * ParoleStream:artist:
+     * 
+     * 
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_ARTIST,
+				     g_param_spec_string ("artist",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_READWRITE));
+							  
+    /**
+     * ParoleStream:year:
+     * 
+     * 
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_YEAR,
+				     g_param_spec_string ("year",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_READWRITE));
+							  
+    /**
+     * ParoleStream:album:
+     * 
+     * 
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_ALBUM,
+				     g_param_spec_string ("album",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_READWRITE));
+							  
+    /**
+     * ParoleStream:comment:
+     * 
+     * 
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_COMMENT,
+				     g_param_spec_string ("comment",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_READWRITE));
+							  
+    g_type_class_add_private (klass, sizeof (ParoleStreamPrivate));
+}
+
+static void
+parole_stream_init (ParoleStream *stream)
+{
+    ParoleStreamPrivate *priv;
+    priv = PAROLE_STREAM_GET_PRIVATE (stream);
+
+    priv->media_file = NULL;
+    parole_stream_init_properties (stream);
+}
+
+ParoleStream *
+parole_stream_new (void)
+{
+    ParoleStream *stream = NULL;
+    stream = g_object_new (PAROLE_TYPE_STREAM, NULL);
+    return stream;
+}
+
+void parole_stream_init_properties (ParoleStream *stream)
+{
+    ParoleStreamPrivate *priv;
+    
+    priv = PAROLE_STREAM_GET_PRIVATE (stream);
+    priv->live = FALSE;
+    priv->seekable = FALSE;
+    priv->has_audio = FALSE;
+    priv->has_video = FALSE;
+    priv->absolute_duration = 0;
+    priv->duration = 0;
+    
+    if ( priv->media_file )
+	g_object_unref (priv->media_file);
+	
+    PAROLE_STREAM_FREE_STR_PROP (priv->title);
+    PAROLE_STREAM_FREE_STR_PROP (priv->artist);
+    PAROLE_STREAM_FREE_STR_PROP (priv->year);
+    PAROLE_STREAM_FREE_STR_PROP (priv->album);
+    PAROLE_STREAM_FREE_STR_PROP (priv->comment);
+	
+    priv->media_file = NULL;
+}

Added: parole/trunk/parole/parole-stream.h
===================================================================
--- parole/trunk/parole/parole-stream.h	                        (rev 0)
+++ parole/trunk/parole/parole-stream.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,54 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_STREAM_H
+#define __PAROLE_STREAM_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_STREAM        (parole_stream_get_type () )
+#define PAROLE_STREAM(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_STREAM, ParoleStream))
+#define PAROLE_IS_STREAM(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_STREAM))
+
+typedef struct _ParoleStream      ParoleStream;
+typedef struct _ParoleStreamClass ParoleStreamClass;
+
+struct _ParoleStream
+{
+    GObject         		parent;
+    
+};
+
+struct _ParoleStreamClass
+{
+    GObjectClass 		parent_class;
+};
+
+GType        			parole_stream_get_type        (void) G_GNUC_CONST;
+
+ParoleStream       	       *parole_stream_new             (void);
+
+void			        parole_stream_init_properties (ParoleStream *stream);
+
+G_END_DECLS
+
+#endif /* __PAROLE_STREAM_H */

Added: parole/trunk/parole/parole-utils.c
===================================================================
--- parole/trunk/parole/parole-utils.c	                        (rev 0)
+++ parole/trunk/parole/parole-utils.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,348 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <gst/gst.h>
+#include <glib.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include "parole-utils.h"
+
+/* List from xine-lib's demux_sputext.c */
+static const char subtitle_ext[][4] = {
+	"asc",
+	"txt",
+	"sub",
+	"srt",
+	"smi",
+	"ssa",
+	"ass"
+};
+
+void parole_window_busy_cursor		(GdkWindow *window)
+{
+    GdkCursor *cursor;
+    
+    if ( G_UNLIKELY (window == NULL) )
+	return;
+	
+    cursor = gdk_cursor_new (GDK_WATCH);
+    gdk_window_set_cursor (window, cursor);
+    gdk_cursor_unref (cursor);
+
+    gdk_flush ();
+}
+
+void parole_window_invisible_cursor		(GdkWindow *window)
+{
+    GdkBitmap *empty_bitmap;
+    GdkCursor *cursor;
+    GdkColor  color;
+
+    char cursor_bits[] = { 0x0 }; 
+    
+    if ( G_UNLIKELY (window == NULL) )
+	return;
+	
+    color.red = color.green = color.blue = 0;
+    color.pixel = 0;
+
+    empty_bitmap = gdk_bitmap_create_from_data (window,
+		   cursor_bits,
+		   1, 1);
+
+    cursor = gdk_cursor_new_from_pixmap (empty_bitmap,
+					 empty_bitmap,
+					 &color,
+					 &color, 0, 0);
+
+    gdk_window_set_cursor (window, cursor);
+
+    gdk_cursor_unref (cursor);
+
+    g_object_unref (empty_bitmap);
+}
+
+/*
+ * compare_by_name_using_number
+ * 
+ * * Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
+ * 
+ */
+static gint
+compare_by_name_using_number (const gchar *ap,
+                              const gchar *bp)
+{
+    guint anum;
+    guint bnum;
+
+    /* determine the numbers in ap and bp */
+    anum = strtoul (ap, NULL, 10);
+    bnum = strtoul (bp, NULL, 10);
+
+    /* compare the numbers */
+    if (anum < bnum)
+	return -1;
+    else if (anum > bnum)
+	return 1;
+
+    /* the numbers are equal, and so the higher first digit should
+    * be sorted first, i.e. 'file10' before 'file010', since we
+    * also sort 'file10' before 'file011'.
+    */
+    return (*bp - *ap);
+}
+
+/*
+ * thunar_file_compare_by_name
+ * 
+ * * Copyright (c) 2005-2007 Benedikt Meurer <benny at xfce.org>
+ * 
+ */
+gint
+thunar_file_compare_by_name (ParoleMediaFile *file_a,
+                             ParoleMediaFile *file_b,
+                             gboolean         case_sensitive)
+{
+    const gchar *ap;
+    const gchar *bp;
+    guint        ac;
+    guint        bc;
+
+
+    /* we compare only the display names (UTF-8!) */
+    ap = parole_media_file_get_display_name (file_a);
+    bp = parole_media_file_get_display_name (file_b);
+
+    /* check if we should ignore case */
+    if (G_LIKELY (case_sensitive))
+    {
+	/* try simple (fast) ASCII comparison first */
+	for (;; ++ap, ++bp)
+        {
+	    /* check if the characters differ or we have a non-ASCII char */
+	    ac = *((const guchar *) ap);
+	    bc = *((const guchar *) bp);
+	    if (ac != bc || ac == 0 || ac > 127)
+		break;
+	}
+
+	/* fallback to Unicode comparison */
+	if (G_UNLIKELY (ac > 127 || bc > 127))
+        {
+	    for (;; ap = g_utf8_next_char (ap), bp = g_utf8_next_char (bp))
+            {
+		/* check if characters differ or end of string */
+		ac = g_utf8_get_char (ap);
+		bc = g_utf8_get_char (bp);
+		if (ac != bc || ac == 0)
+		    break;
+	    }
+        }
+    }
+    else
+    {
+	/* try simple (fast) ASCII comparison first (case-insensitive!) */
+	for (;; ++ap, ++bp)
+        {
+	    /* check if the characters differ or we have a non-ASCII char */
+	    ac = *((const guchar *) ap);
+	    bc = *((const guchar *) bp);
+	    if (g_ascii_tolower (ac) != g_ascii_tolower (bc) || ac == 0 || ac > 127)
+		break;
+        }
+
+	/* fallback to Unicode comparison (case-insensitive!) */
+	if (G_UNLIKELY (ac > 127 || bc > 127))
+	{
+	    for (;; ap = g_utf8_next_char (ap), bp = g_utf8_next_char (bp))
+            {
+		/* check if characters differ or end of string */
+		ac = g_utf8_get_char (ap);
+		bc = g_utf8_get_char (bp);
+		if (g_unichar_tolower (ac) != g_unichar_tolower (bc) || ac == 0)
+		    break;
+            }
+        }
+    }
+
+    /* if both strings are equal, we're done */
+    if (G_UNLIKELY (ac == bc || (!case_sensitive && g_unichar_tolower (ac) == g_unichar_tolower (bc))))
+	return 0;
+
+    /* check if one of the characters that differ is a digit */
+    if (G_UNLIKELY (g_ascii_isdigit (ac) || g_ascii_isdigit (bc)))
+    {
+	/* if both strings differ in a digit, we use a smarter comparison
+	 * to get sorting 'file1', 'file5', 'file10' done the right way.
+	 */
+	if (g_ascii_isdigit (ac) && g_ascii_isdigit (bc))
+	    return compare_by_name_using_number (ap, bp);
+
+	/* a second case is '20 file' and '2file', where comparison by number
+	 * makes sense, if the previous char for both strings is a digit.
+	 */
+	if (ap > parole_media_file_get_display_name (file_a) && bp > parole_media_file_get_display_name (file_b)
+	    && g_ascii_isdigit (*(ap - 1)) && g_ascii_isdigit (*(bp - 1)))
+        {
+	    return compare_by_name_using_number (ap - 1, bp - 1);
+        }
+    }
+
+    /* otherwise, if they differ in a unicode char, use the
+     * appropriate collate function for the current locale (only
+     * if charset is UTF-8, else the required transformations
+     * would be too expensive)
+     */
+#ifdef HAVE_STRCOLL
+    if ((ac > 127 || bc > 127) && g_get_charset (NULL))
+    {
+	/* case-sensitive is easy, case-insensitive is expensive,
+         * but we use a simple optimization to make it fast.
+         */
+	if (G_LIKELY (case_sensitive))
+        {
+	    return strcoll (ap, bp);
+        }
+	else
+        {
+	    /* we use a trick here, so we don't need to allocate
+             * and transform the two strings completely first (8
+             * byte for each buffer, so all compilers should align
+             * them properly)
+             */
+	    gchar abuf[8];
+	    gchar bbuf[8];
+
+	    /* transform the unicode chars to strings and
+             * make sure the strings are nul-terminated.
+	     */
+	    abuf[g_unichar_to_utf8 (ac, abuf)] = '\0';
+	    bbuf[g_unichar_to_utf8 (bc, bbuf)] = '\0';
+
+	    /* compare the unicode chars (as strings) */
+	    return strcoll (abuf, bbuf);
+        }
+    }
+#endif
+
+    /* else, they differ in an ASCII character */
+    if (G_UNLIKELY (!case_sensitive))
+	return (g_unichar_tolower (ac) > g_unichar_tolower (bc)) ? 1 : -1;
+    else
+	return (ac > bc) ? 1 : -1;
+}
+
+gchar *
+parole_get_name_without_extension (const gchar *name)
+{
+    guint len, suffix;
+    gchar *ret;
+    
+    len = strlen (name);
+    
+    for ( suffix = len -1; suffix > 0;  suffix--)
+    {
+	if ( name [suffix] == '.' )
+	    break;
+    }
+    
+    ret = g_strndup (name, sizeof (char) * (suffix));
+    return ret;
+}
+
+static gchar *
+parole_get_subtitle_in_dir (const gchar *dir_path, const gchar *file)
+{
+    gchar *sub_path = NULL;
+    gchar *file_no_ext;
+    guint i;
+    
+    file_no_ext = parole_get_name_without_extension (file);
+    
+    for ( i = 0; i < G_N_ELEMENTS (subtitle_ext); i++)
+    {
+	sub_path = g_strdup_printf ("%s/%s.%s", dir_path, file_no_ext, subtitle_ext[i]);
+	
+	if ( g_file_test (sub_path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR ) )
+	    break;
+
+	g_free (sub_path);
+	sub_path = NULL;
+    }
+    g_free (file_no_ext);
+    
+    return sub_path;
+}
+
+gchar *parole_get_subtitle_path (const gchar *uri)
+{
+    GFile *file, *parent;
+    GFileInfo *info;
+    GError *error = NULL;
+    gchar *path;
+    gchar *file_name;
+    gchar *ret = NULL;
+    
+    file = g_file_new_for_commandline_arg (uri);
+    parent = g_file_get_parent (file);
+    
+    if ( !parent )
+    {
+	g_object_unref (file);
+	return NULL;
+    }
+    
+    info = g_file_query_info (file, 
+			      "standard::*,",
+			      0,
+			      NULL,
+			      &error);
+    
+    if ( error )
+    {
+	g_warning ("%s: \n", error->message);
+	g_error_free (error);
+	return NULL;
+    }
+    
+    file_name = g_strdup (g_file_info_get_display_name (info));
+    
+    path = g_file_get_path (parent);
+    
+    ret = parole_get_subtitle_in_dir (path, file_name);
+
+    g_object_unref (file);
+    g_object_unref (parent);
+    g_object_unref (info);
+    
+    g_free (file_name);
+    g_free (path);
+    
+    return ret;
+}

Added: parole/trunk/parole/parole-utils.h
===================================================================
--- parole/trunk/parole/parole-utils.h	                        (rev 0)
+++ parole/trunk/parole/parole-utils.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,41 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_UTILS_H_
+#define __PAROLE_UTILS_H_
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "parole-mediafile.h"
+
+void		parole_window_busy_cursor		(GdkWindow *window);
+
+void		parole_window_invisible_cursor		(GdkWindow *window);
+
+gint            thunar_file_compare_by_name 		(ParoleMediaFile *file_a,
+							 ParoleMediaFile *file_b,
+							 gboolean         case_sensitive);
+
+gchar          *parole_get_name_without_extension 	(const gchar *name)G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+
+gchar          *parole_get_subtitle_path		(const gchar *uri) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
+
+#endif /* __PAROLE_UTILS_ */

Added: parole/trunk/parole/parole-vis.c
===================================================================
--- parole/trunk/parole/parole-vis.c	                        (rev 0)
+++ parole/trunk/parole/parole-vis.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,73 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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 <gst/gst.h>
+#include <glib.h>
+
+#include "parole-vis.h"
+
+static gboolean
+parole_vis_filter (GstPluginFeature *feature, gpointer data)
+{
+    GstElementFactory *factory;
+    
+    if ( !GST_IS_ELEMENT_FACTORY (feature) )
+	return FALSE;
+	
+    factory = GST_ELEMENT_FACTORY (feature);
+    
+    if ( !g_strrstr (gst_element_factory_get_klass (factory), "Visualization"))
+	return FALSE;
+	
+    return TRUE;
+}
+
+static void
+parole_vis_get_name (GstElementFactory *factory, GHashTable **hash)
+{
+    g_hash_table_insert (*hash, g_strdup (gst_element_factory_get_longname (factory)), factory);
+}
+
+GHashTable *parole_vis_get_plugins (void)
+{
+    GList *plugins = NULL;
+    GHashTable *hash;
+    
+    hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+    
+    plugins = gst_registry_feature_filter (gst_registry_get_default (),
+					   parole_vis_filter,
+					   FALSE,
+					   NULL);
+					   
+    g_list_foreach (plugins, (GFunc) parole_vis_get_name, &hash);
+    
+    gst_plugin_feature_list_free (plugins);
+    
+    return hash;
+}

Added: parole/trunk/parole/parole-vis.h
===================================================================
--- parole/trunk/parole/parole-vis.h	                        (rev 0)
+++ parole/trunk/parole/parole-vis.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,31 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#ifndef __PAROLE_VIS_H_
+#define __PAROLE_VIS_H_
+
+#include <gst/gst.h>
+#include <glib.h>
+
+GHashTable        *parole_vis_get_plugins			(void);
+
+//GstElement	*parole_vis_get_for_name		(void)
+
+#endif /* __PAROLE_VIS_H_ */

Added: parole/trunk/parole/parole.h
===================================================================
--- parole/trunk/parole/parole.h	                        (rev 0)
+++ parole/trunk/parole/parole.h	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,53 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#include <parole/parole-plugin.h>
+
+ParolePlugin     *parole_plugin_constructor     (void);
+
+/**
+ * ParolePluginConstruct:
+ * @plugin: A #ParolePlugin.
+ * 
+ * Argument registration function to be used with 
+ * the registration macro PAROLE_PLUGIN_CONSTRUCT().
+ * 
+ **/
+typedef void 	(*ParolePluginConstruct)	(ParolePlugin *plugin);
+
+/**
+ * PAROLE_PLUGIN_CONSTRUCT:
+ * @construct: a function that can be cast to #ParolePluginConstruct type.
+ * @title: title.
+ * @desc: description.
+ * @author: author.
+ * 
+ **/
+#define PAROLE_PLUGIN_CONSTRUCT(construct, title, desc, author)		\
+    G_MODULE_EXPORT ParolePlugin *parole_plugin_constructor (void)	\
+    {									\
+	ParolePlugin *plugin;						\
+	ParolePluginConstruct constructor 				\
+	    = (ParolePluginConstruct) construct;			\
+									\
+	plugin = parole_plugin_new (title, desc, author);		\
+	constructor (plugin);						\
+	return plugin;							\
+    }

Added: parole/trunk/plugins/Makefile.am
===================================================================
--- parole/trunk/plugins/Makefile.am	                        (rev 0)
+++ parole/trunk/plugins/Makefile.am	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,5 @@
+SUBDIRS = 
+
+if PAROLE_PROPERTIES_PLUGIN
+SUBDIRS+=properties
+endif

Added: parole/trunk/plugins/properties/Makefile.am
===================================================================
--- parole/trunk/plugins/properties/Makefile.am	                        (rev 0)
+++ parole/trunk/plugins/properties/Makefile.am	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,25 @@
+INCLUDES =					\
+	-I$(top_builddir)			\
+	-I$(top_srcdir)				\
+	-DG_LOG_DOMAIN=\"stream_properties\"    \
+	-DLIBEXECDIR=\"$(libexecdir)\"		\
+	-DPACKAGE_LOCALE_DIR=\"$(localedir)\"
+
+pluginsdir = 					\
+	$(libdir)/parole-$(PAROLE_VERSION_API)
+
+plugins_LTLIBRARIES =				\
+	stream-properties.la
+
+stream_properties_la_SOURCES =			\
+	stream-properties.c
+
+stream_properties_la_CFLAGS =			\
+	$(PLATFORM_CFLAGS)			\
+	$(GTK_CFLAGS)
+
+stream_properties_la_LDFLAGS =			\
+	-avoid-version				\
+	-export-dynamic				\
+	-module					\
+	$(PLATFORM_LDFLAGS)

Added: parole/trunk/plugins/properties/stream-properties.c
===================================================================
--- parole/trunk/plugins/properties/stream-properties.c	                        (rev 0)
+++ parole/trunk/plugins/properties/stream-properties.c	2009-07-16 15:03:06 UTC (rev 7735)
@@ -0,0 +1,286 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at 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
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+
+#include <parole/parole.h>
+
+typedef struct
+{
+    GtkWidget *title;
+    GtkWidget *artist;
+    GtkWidget *album;
+    GtkWidget *year;
+    GtkWidget *comment;
+    
+} PluginData;
+
+static void
+init_media_tag_entries (PluginData *data)
+{
+    gtk_entry_set_text (GTK_ENTRY (data->title), _("Unknown"));
+    gtk_entry_set_text (GTK_ENTRY (data->artist), _("Unknown"));
+    gtk_entry_set_text (GTK_ENTRY (data->album), _("Unknown"));
+    gtk_entry_set_text (GTK_ENTRY (data->year), _("Unknown"));
+    gtk_entry_set_text (GTK_ENTRY (data->comment), _("Unknown"));
+}
+
+static GtkWidget *create_properties_widget (PluginData *data)
+{
+    PangoFontDescription *pfd;
+    
+    GtkWidget *label;
+    GtkWidget *vbox;
+    GtkWidget *table;
+    GtkWidget *align;
+    guint i = 0;
+    
+    vbox = gtk_vbox_new (FALSE, 0);
+    table = gtk_table_new (5, 2, FALSE);
+    pfd = pango_font_description_from_string("bold");
+    
+    /*
+     * Title
+     */
+    align = gtk_alignment_new (0.0, 0.5, 0, 0);
+    
+    label = gtk_label_new (_("Title:"));
+    gtk_container_add (GTK_CONTAINER(align), label);
+    gtk_widget_modify_font (label, pfd);
+    
+    gtk_table_attach (GTK_TABLE(table), align,
+		      0, 1, i, i+1, 
+                      GTK_SHRINK, GTK_SHRINK,
+                      2, 8);
+
+    data->title = gtk_entry_new ();
+    align = gtk_alignment_new (0.0, 0.5, 0, 0);
+    gtk_container_add (GTK_CONTAINER (align), data->title);
+    gtk_table_attach (GTK_TABLE (table), align,
+                      1, 2, i, i+1, 
+                      GTK_SHRINK, GTK_SHRINK,
+                      2, 8);
+    i++;
+
+    /*
+     * Artist
+     */
+    align = gtk_alignment_new (0.0, 0.5, 0, 0);
+    
+    label = gtk_label_new (_("Artist:"));
+    gtk_container_add (GTK_CONTAINER(align), label);
+    gtk_widget_modify_font (label, pfd);
+    
+    gtk_table_attach (GTK_TABLE(table), align,
+		      0, 1, i, i+1, 
+                      GTK_SHRINK, GTK_SHRINK,
+                      2, 8);
+
+    data->artist = gtk_entry_new ();
+    align = gtk_alignment_new (0.0, 0.5, 0, 0);
+    gtk_container_add (GTK_CONTAINER (align), data->artist);
+    gtk_table_attach (GTK_TABLE (table), align,
+                      1, 2, i, i+1, 
+                      GTK_SHRINK, GTK_SHRINK,
+                      2, 8);
+    i++;
+
+    /*
+     * Album
+     */
+    align = gtk_alignment_new (0.0, 0.5, 0, 0);
+    
+    label = gtk_label_new (_("Album:"));
+    gtk_container_add (GTK_CONTAINER(align), label);
+    gtk_widget_modify_font (label, pfd);
+    
+    gtk_table_attach (GTK_TABLE(table), align,
+		      0, 1, i, i+1, 
+                      GTK_SHRINK, GTK_SHRINK,
+                      2, 8);
+
+    data->album = gtk_entry_new ();
+    align = gtk_alignment_new (0.0, 0.5, 0, 0);
+    gtk_container_add (GTK_CONTAINER (align), data->album);
+    gtk_table_attach (GTK_TABLE (table), align,
+                      1, 2, i, i+1, 
+                      GTK_SHRINK, GTK_SHRINK,
+                      2, 8);
+    i++;
+    
+    /*
+     * Year
+     */
+    align = gtk_alignment_new (0.0, 0.5, 0, 0);
+    
+    label = gtk_label_new (_("Year:"));
+    gtk_container_add (GTK_CONTAINER (align), label);
+    gtk_widget_modify_font (label, pfd);
+    
+    gtk_table_attach (GTK_TABLE(table), align,
+		      0, 1, i, i+1, 
+                      GTK_SHRINK, GTK_SHRINK,
+                      2, 8);
+
+    data->year = gtk_entry_new ();
+    align = gtk_alignment_new (0.0, 0.5, 0, 0);
+    gtk_container_add (GTK_CONTAINER (align), data->year);
+    gtk_table_attach (GTK_TABLE (table), align,
+                      1, 2, i, i+1, 
+                      GTK_SHRINK, GTK_SHRINK,
+                      2, 8);
+    i++;
+    
+    /*
+     * Comment
+     */
+    align = gtk_alignment_new (0.0, 0.5, 0, 0);
+    
+    label = gtk_label_new (_("Comment:"));
+    gtk_container_add (GTK_CONTAINER(align), label);
+    gtk_widget_modify_font (label, pfd);
+    
+    gtk_table_attach (GTK_TABLE(table), align,
+		      0, 1, i, i+1, 
+                      GTK_SHRINK, GTK_SHRINK,
+                      2, 8);
+
+    data->comment = gtk_entry_new ();
+    align = gtk_alignment_new (0.0, 0.5, 0, 0);
+    gtk_container_add (GTK_CONTAINER (align), data->comment);
+    gtk_table_attach (GTK_TABLE (table), align,
+                      1, 2, i, i+1, 
+                      GTK_SHRINK, GTK_SHRINK,
+                      2, 8);
+    i++;
+    
+    gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+    
+    init_media_tag_entries (data);
+    
+#ifndef HAVE_CTAG_LIB
+    gtk_entry_set_editable (GTK_ENTRY (data->title), FALSE);
+    gtk_entry_set_editable (GTK_ENTRY (data->album), FALSE);
+    gtk_entry_set_editable (GTK_ENTRY (data->artist), FALSE);
+    gtk_entry_set_editable (GTK_ENTRY (data->year), FALSE);
+    gtk_entry_set_editable (GTK_ENTRY (data->comment), FALSE);
+#endif
+
+    return vbox;
+}
+
+static void
+state_changed_cb (ParolePlugin *plugin, const ParoleStream *stream, ParoleState state, PluginData *data)
+{
+    if ( state <= PAROLE_STATE_PLAYBACK_FINISHED )
+	init_media_tag_entries (data);
+}
+
+static void
+tag_message_cb (ParolePlugin *plugin, const ParoleStream *stream, PluginData *data)
+{
+    gchar *str = NULL;
+    
+    g_object_get (G_OBJECT (stream),
+		  "title", &str,
+		  NULL);
+		  
+    if ( str )
+    {
+	gtk_entry_set_text (GTK_ENTRY (data->title), str);
+	g_free (str);
+    }
+    
+    g_object_get (G_OBJECT (stream),
+		  "comment", &str,
+		  NULL);
+		  
+    if ( str )
+    {
+	gtk_entry_set_text (GTK_ENTRY (data->comment), str);
+	g_free (str);
+    }
+    
+    g_object_get (G_OBJECT (stream),
+		  "artist", &str,
+		  NULL);
+		  
+    if ( str )
+    {
+	gtk_entry_set_text (GTK_ENTRY (data->artist), str);
+	g_free (str);
+    }
+    
+    g_object_get (G_OBJECT (stream),
+		  "year", &str,
+		  NULL);
+		  
+    if ( str )
+    {
+	gtk_entry_set_text (GTK_ENTRY (data->year), str);
+	g_free (str);
+    }
+    
+    g_object_get (G_OBJECT (stream),
+		  "album", &str,
+		  NULL);
+		  
+    if ( str )
+    {
+	gtk_entry_set_text (GTK_ENTRY (data->album), str);
+	g_free (str);
+    }
+    
+}
+
+static void
+free_data_cb (ParolePlugin *plugin, PluginData *data)
+{
+    g_free (data);
+}
+
+G_MODULE_EXPORT static void
+construct (ParolePlugin *plugin)
+{
+    PluginData *data;
+    GtkWidget *vbox;
+    
+    data = g_new0 (PluginData, 1);
+    
+    vbox = create_properties_widget (data);
+    
+    parole_plugin_pack_widget (plugin, vbox, PAROLE_PLUGIN_CONTAINER_PLAYLIST);
+    
+    g_signal_connect (plugin, "state_changed", 
+		      G_CALLBACK (state_changed_cb), data);
+		      
+    g_signal_connect (plugin, "tag-message",
+		      G_CALLBACK (tag_message_cb), data);
+    
+    g_signal_connect (plugin, "free-data",
+		      G_CALLBACK (free_data_cb), data);
+}
+
+PAROLE_PLUGIN_CONSTRUCT (construct,                  /* Construct function */
+			 _("Properties"),            /* Title */
+			 _("Read media properties"), /* Description */
+			 "Ali Abdallah");            /* Author */

Modified: parole/trunk/po/POTFILES.in
===================================================================
--- parole/trunk/po/POTFILES.in	2009-07-16 15:03:04 UTC (rev 7734)
+++ parole/trunk/po/POTFILES.in	2009-07-16 15:03:06 UTC (rev 7735)
@@ -5,12 +5,12 @@
 [type: gettext/glade]data/interfaces/openlocation.ui
 [type: gettext/glade]data/interfaces/parole-settings.ui
 data/desktop/parole.desktop.in.in
-src/main.c
-src/gst.c
-src/builder.c
-src/mediachooser.c
-src/medialist.c
-src/player.c
-src/sidebar.c
-src/statusbar.c
-src/filters.c
+parole/main.c
+parole/parole-gst.c
+parole/parole-mediachooser.c
+parole/parole-medialist.c
+parole/parole-player.c
+parole/parole-sidebar.c
+parole/parole-statusbar.c
+parole/parole-filters.c
+plugins/properties/stream-properties.c

Modified: parole/trunk/po/parole-media-player.pot
===================================================================
--- parole/trunk/po/parole-media-player.pot	2009-07-16 15:03:04 UTC (rev 7734)
+++ parole/trunk/po/parole-media-player.pot	2009-07-16 15:03:06 UTC (rev 7735)
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-07-07 09:09+0200\n"
+"POT-Creation-Date: 2009-07-16 16:57+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
@@ -21,34 +21,30 @@
 msgstr ""
 
 #: ../data/interfaces/parole.ui.h:2
-msgid "Audio converter"
+msgid "Media player"
 msgstr ""
 
 #: ../data/interfaces/parole.ui.h:3
-msgid "Audio recorder"
+msgid "Nothing yet."
 msgstr ""
 
 #: ../data/interfaces/parole.ui.h:4
-msgid "Media player"
+msgid "Plugins"
 msgstr ""
 
 #: ../data/interfaces/parole.ui.h:5
-msgid "Nothing yet."
+msgid "_Edit"
 msgstr ""
 
 #: ../data/interfaces/parole.ui.h:6
-msgid "_Edit"
+msgid "_Help"
 msgstr ""
 
 #: ../data/interfaces/parole.ui.h:7
-msgid "_File"
+msgid "_Media"
 msgstr ""
 
 #: ../data/interfaces/parole.ui.h:8
-msgid "_Help"
-msgstr ""
-
-#: ../data/interfaces/parole.ui.h:9
 msgid "_View"
 msgstr ""
 
@@ -108,106 +104,149 @@
 msgid "gtk-help"
 msgstr ""
 
-#: ../data/desktop/parole.desktop.in.in.h:1
+#: ../data/desktop/parole.desktop.in.in.h:1 ../parole/parole-player.c:156
 msgid "Parole Media Player"
 msgstr ""
 
-#: ../src/main.c:97
+#: ../parole/main.c:103
+msgid "Open a new instance"
+msgstr ""
+
+#: ../parole/main.c:104
 msgid "Media to play"
 msgstr ""
 
-#: ../src/main.c:113
+#: ../parole/main.c:120
 #, c-format
 msgid "Type '%s --help' for usage."
 msgstr ""
 
-#: ../src/gst.c:726
+#: ../parole/parole-gst.c:787
 msgid "Error in changing state to ready"
 msgstr ""
 
-#: ../src/gst.c:775
+#: ../parole/parole-gst.c:836
 msgid ""
 "Unable to load playbin GStreamer plugin, check your GStreamer installation"
 msgstr ""
 
-#: ../src/gst.c:790
+#: ../parole/parole-gst.c:851
 msgid ""
 "Unable to load video GStreamer plugin, check your GStreamer installation"
 msgstr ""
 
-#: ../src/builder.c:69
-msgid "Check your Parole installation"
-msgstr ""
-
-#: ../src/mediachooser.c:197
+#: ../parole/parole-mediachooser.c:203
 msgid "Add media files"
 msgstr ""
 
-#: ../src/mediachooser.c:197
+#: ../parole/parole-mediachooser.c:203
 msgid "Open media file"
 msgstr ""
 
-#: ../src/mediachooser.c:214
+#: ../parole/parole-mediachooser.c:220
 msgid "Add"
 msgstr ""
 
-#: ../src/mediachooser.c:214
+#: ../parole/parole-mediachooser.c:220
 msgid "Open"
 msgstr ""
 
-#: ../src/medialist.c:503
+#: ../parole/parole-medialist.c:506
 msgid "Media list"
 msgstr ""
 
-#: ../src/player.c:171
+#: ../parole/parole-player.c:177
 msgid "Hide playlist"
 msgstr ""
 
-#: ../src/player.c:180
+#: ../parole/parole-player.c:186
 msgid "Show playlist"
 msgstr ""
 
-#: ../src/player.c:313 ../src/statusbar.c:125 ../src/statusbar.c:127
+#: ../parole/parole-player.c:319 ../parole/parole-statusbar.c:126
+#: ../parole/parole-statusbar.c:128
 msgid "Playing"
 msgstr ""
 
-#: ../src/player.c:314
+#: ../parole/parole-player.c:320
 msgid "Media stream is not seekable"
 msgstr ""
 
-#: ../src/player.c:332 ../src/player.c:345
+#: ../parole/parole-player.c:338 ../parole/parole-player.c:351
 msgid "Paused"
 msgstr ""
 
-#: ../src/player.c:363
+#: ../parole/parole-player.c:369
 msgid "Stopped"
 msgstr ""
 
-#: ../src/sidebar.c:137
+#: ../parole/parole-player.c:931
+msgid "Playlist"
+msgstr ""
+
+#: ../parole/parole-sidebar.c:138
 msgid ""
 "<b>Media \n"
 "player\n"
 "</b>"
 msgstr ""
 
-#: ../src/sidebar.c:147
+#: ../parole/parole-sidebar.c:148
 msgid ""
 "<b>Albums\n"
 "</b>"
 msgstr ""
 
-#: ../src/statusbar.c:137
+#: ../parole/parole-statusbar.c:138
 msgid "Buffering"
 msgstr ""
 
-#: ../src/filters.c:46
+#: ../parole/parole-filters.c:46
 msgid "Audio"
 msgstr ""
 
-#: ../src/filters.c:64
+#: ../parole/parole-filters.c:64
 msgid "Video"
 msgstr ""
 
-#: ../src/filters.c:82
+#: ../parole/parole-filters.c:82
 msgid "Audio and video"
 msgstr ""
+
+#: ../plugins/properties/stream-properties.c:40
+#: ../plugins/properties/stream-properties.c:41
+#: ../plugins/properties/stream-properties.c:42
+#: ../plugins/properties/stream-properties.c:43
+#: ../plugins/properties/stream-properties.c:44
+msgid "Unknown"
+msgstr ""
+
+#: ../plugins/properties/stream-properties.c:66
+msgid "Title:"
+msgstr ""
+
+#: ../plugins/properties/stream-properties.c:89
+msgid "Artist:"
+msgstr ""
+
+#: ../plugins/properties/stream-properties.c:112
+msgid "Album:"
+msgstr ""
+
+#: ../plugins/properties/stream-properties.c:135
+msgid "Year:"
+msgstr ""
+
+#: ../plugins/properties/stream-properties.c:158
+msgid "Comment:"
+msgstr ""
+
+#. Construct function
+#: ../plugins/properties/stream-properties.c:284
+msgid "Properties"
+msgstr ""
+
+#. Title
+#: ../plugins/properties/stream-properties.c:285
+msgid "Read media properties"
+msgstr ""




More information about the Goodies-commits mailing list