[Xfce4-commits] <parole:master> Support for playlist format in the media browser plugin.

Ali Abdallah noreply at xfce.org
Fri Nov 27 10:02:02 CET 2009


Updating branch refs/heads/master
         to ce2b8cfa71b936f086b7dec5cbc0495febf6c036 (commit)
       from 43006e0f381ffa329b45543f599a48ad81c033bd (commit)

commit ce2b8cfa71b936f086b7dec5cbc0495febf6c036
Author: Ali Abdallah <ali at ali-xfce.org>
Date:   Thu Nov 26 23:03:17 2009 +0100

    Support for playlist format in the media browser plugin.

 browser-plugin/Makefile.am                         |   11 +-
 browser-plugin/media-plugin/main.c                 |    4 +-
 .../media-plugin/org.parole.media.plugin.xml       |    7 +
 browser-plugin/media-plugin/parole-plugin-player.c |  136 ++++---
 browser-plugin/media-plugin/parole-plugin-player.h |    4 +-
 browser-plugin/npp_gate.cpp                        |   10 +-
 browser-plugin/parole-plugin.c                     |  464 ++++++++++++++++++++
 browser-plugin/parole-plugin.h                     |   76 ++++
 browser-plugin/plugin.cpp                          |  220 +---------
 browser-plugin/plugin.h                            |   40 +--
 gst/parole-gst.c                                   |    7 +-
 parole/Makefile.am                                 |   15 +-
 {src => parole}/parole-debug.c                     |    0
 {src => parole}/parole-debug.h                     |    0
 parole/parole-filters.c                            |  148 +++++++
 {src => parole}/parole-filters.h                   |    9 +-
 {src => parole}/parole-pl-parser.c                 |   85 +++-
 {src => parole}/parole-pl-parser.h                 |    9 +-
 parole/parole.h.in                                 |    3 +
 src/Makefile.am                                    |    8 -
 src/parole-filters.c                               |  225 ----------
 src/parole-utils.c                                 |   78 ++++
 src/parole-utils.h                                 |    5 +
 23 files changed, 1015 insertions(+), 549 deletions(-)

diff --git a/browser-plugin/Makefile.am b/browser-plugin/Makefile.am
index 09eeef2..606b622 100644
--- a/browser-plugin/Makefile.am
+++ b/browser-plugin/Makefile.am
@@ -22,12 +22,15 @@ INCLUDES =                                              \
         -fPIC                                           \
         -I$(top_builddir)                               \
         -I$(top_srcdir)                                 \
+	-I$(top_srcdir)/parole                         	\
         -DPACKAGE_LOCALE_DIR=\"$(localedir)\"           \
         -DG_LOG_DOMAIN=\"parole-browser-plugin\"        \
         -DLIBEXECDIR="\"$(libexecdir)\""                \
 	$(GECKO_CFLAGS)					\
         $(GTK_CFLAGS)                                   \
         $(DBUS_GLIB_CFLAGS)				\
+	$(TAGLIBC_CFLAGS)				\
+	$(LIBXFCE4UTIL_CFLAGS)
 	$(DEFINES)
 
 install_libexecdir = $(BROWSER_PLUGIN_DIR)
@@ -38,6 +41,8 @@ install_libexec_PROGRAMS = 				\
 parole_player_so_SOURCES =     				\
 	plugin.cpp					\
 	plugin.h					\
+	parole-plugin.c					\
+	parole-plugin.h					\
 	plugin_setup.cpp  				\
 	plugin_setup.h					\
 	plugin_types.cpp				\
@@ -51,5 +56,7 @@ parole_player_so_LDFLAGS =                              \
 	-Xcompiler					\
 	-shared						\
         $(GTK_LIBS)                                     \
-        $(DBUS_GLIB_LIBS)
-
+        $(DBUS_GLIB_LIBS)				\
+	$(TAGLIBC_LIBS)					\
+	$(LIBXFCE4UTIL_LIBS)				\
+	$(top_builddir)/parole/libparole.la
diff --git a/browser-plugin/media-plugin/main.c b/browser-plugin/media-plugin/main.c
index 8a8215c..3877588 100644
--- a/browser-plugin/media-plugin/main.c
+++ b/browser-plugin/media-plugin/main.c
@@ -109,8 +109,6 @@ int main (int argc, char **argv)
     dbus_name = g_strdup_printf ("org.Parole.Media.Plugin%d", socket_id);
     parole_dbus_register_name (dbus_name);
     
-    g_assert (url != NULL);
-    
     plug = gtk_plug_new (socket_id);
 	
     player = parole_plugin_player_new (plug, url);
@@ -128,7 +126,7 @@ int main (int argc, char **argv)
         g_error_free (error);
     }
 
-    parole_plugin_player_play (player);
+    //parole_plugin_player_play (player);
     
     gtk_main ();
     g_object_unref (player);
diff --git a/browser-plugin/media-plugin/org.parole.media.plugin.xml b/browser-plugin/media-plugin/org.parole.media.plugin.xml
index 42ed852..264373a 100644
--- a/browser-plugin/media-plugin/org.parole.media.plugin.xml
+++ b/browser-plugin/media-plugin/org.parole.media.plugin.xml
@@ -14,6 +14,13 @@
     <method name="Ping">
     </method>
     
+    <method name="PlayUrl">
+	<arg type="s" name="url" direction="in"/>
+    </method>
+    
+    <signal name="Ready">
+    </signal>
+    
     <signal name="Exiting">
     </signal>
     
diff --git a/browser-plugin/media-plugin/parole-plugin-player.c b/browser-plugin/media-plugin/parole-plugin-player.c
index 852d767..481fe24 100644
--- a/browser-plugin/media-plugin/parole-plugin-player.c
+++ b/browser-plugin/media-plugin/parole-plugin-player.c
@@ -98,6 +98,7 @@ enum
 enum
 {
     SIG_EXITING,
+    SIG_READY,
     LAST_SIGNAL
 };
 
@@ -106,6 +107,17 @@ static guint signals [LAST_SIGNAL] = { 0 };
 G_DEFINE_TYPE (ParolePluginPlayer, parole_plugin_player, G_TYPE_OBJECT)
 
 static void
+parole_plugin_player_play (ParolePluginPlayer *player)
+{
+    if ( player->priv->terminate )
+	return;
+	
+    player->priv->reload = FALSE;
+    player->priv->finished = FALSE;
+    parole_gst_play_uri (player->priv->gst, player->priv->url, NULL);
+}
+
+static void
 parole_plugin_player_set_fullscreen_button (ParolePluginPlayer *player)
 {
     GtkWidget *img;
@@ -489,6 +501,45 @@ parole_plugin_player_gst_widget_button_press (GtkWidget *widget, GdkEventButton
     return ret_val;
 }
 
+static gboolean
+parole_plugin_player_window_delete_event_cb (ParolePluginPlayer *player)
+{
+    parole_plugin_player_fullscreen (player, FALSE);
+    return TRUE;
+}
+
+static gpointer *check_idle_thread (gpointer data)
+{
+    ParolePluginPlayer *player;
+    
+    player = PAROLE_PLUGIN_PLAYER (data);
+    
+    do
+    {
+	g_usleep (1000000);
+	if ( g_timer_elapsed (idle_timer, NULL ) > 60.f )
+	{
+	    g_signal_emit (player, signals [SIG_EXITING], 0);
+	    gtk_main_quit ();
+	}
+	
+    } while ( player->priv->terminate == FALSE ); 
+
+    return NULL;
+}
+
+static void
+parole_plugin_player_dispose (GObject *object)
+{
+    ParolePluginPlayer *player;
+    
+    player = PAROLE_PLUGIN_PLAYER (object);
+    
+    g_signal_emit (player, signals [SIG_EXITING], 0);
+    
+    G_OBJECT_CLASS (parole_plugin_player_parent_class)->dispose (object);
+}
+
 static void
 parole_plugin_player_construct (GObject *object)
 {
@@ -627,48 +678,8 @@ parole_plugin_player_construct (GObject *object)
     gtk_widget_set_sensitive (player->priv->range, FALSE);
     
     player->priv->vbox = vbox;
-}
-
-static gboolean
-parole_plugin_player_window_delete_event_cb (ParolePluginPlayer *player)
-{
-    parole_plugin_player_fullscreen (player, FALSE);
-    return TRUE;
-}
-
-static gpointer *check_idle_thread (gpointer data)
-{
-    ParolePluginPlayer *player;
-    
-    player = PAROLE_PLUGIN_PLAYER (data);
     
-    do
-    {
-	g_usleep (1000000);
-	if ( g_timer_elapsed (idle_timer, NULL ) > 60.f )
-	{
-	    g_debug ("Idle timeout expired, exiting...");
-	    g_signal_emit (player, signals [SIG_EXITING], 0);
-	    g_debug ("Here");
-	    gtk_main_quit ();
-	    g_debug ("Yalla");
-	}
-	
-    } while ( player->priv->terminate == FALSE ); 
-
-    return NULL;
-}
-
-static void
-parole_plugin_player_dispose (GObject *object)
-{
-    ParolePluginPlayer *player;
-    
-    player = PAROLE_PLUGIN_PLAYER (object);
-    
-    g_signal_emit (player, signals [SIG_EXITING], 0);
-    
-    G_OBJECT_CLASS (parole_plugin_player_parent_class)->dispose (object);
+    g_signal_emit (player, signals [SIG_READY], 0);
 }
 
 static void
@@ -693,6 +704,15 @@ parole_plugin_player_class_init (ParolePluginPlayerClass *klass)
                       g_cclosure_marshal_VOID__VOID,
                       G_TYPE_NONE, 0, G_TYPE_NONE);
     
+    signals[SIG_READY] = 
+        g_signal_new ("ready",
+                      PAROLE_TYPE_PLUGIN_PLAYER,
+                      G_SIGNAL_RUN_LAST,
+                      G_STRUCT_OFFSET (ParolePluginPlayerClass, ready),
+                      NULL, NULL,
+                      g_cclosure_marshal_VOID__VOID,
+                      G_TYPE_NONE, 0, G_TYPE_NONE);
+    
     
     g_object_class_install_property (object_class,
                                      PROP_PLUG,
@@ -814,6 +834,17 @@ parole_plugin_player_finalize (GObject *object)
     G_OBJECT_CLASS (parole_plugin_player_parent_class)->finalize (object);
 }
 
+static gboolean parole_plugin_player_play_idle (gpointer data)
+{
+    ParolePluginPlayer *player;
+    
+    player = PAROLE_PLUGIN_PLAYER (data);
+    
+    parole_plugin_player_play (player);
+    
+    return FALSE;
+}
+
 static gboolean
 parole_plugin_player_quit_idle (gpointer data)
 {
@@ -852,16 +883,6 @@ parole_plugin_player_new (GtkWidget *plug, gchar *url)
     return player;
 }
 
-void parole_plugin_player_play (ParolePluginPlayer *player)
-{
-    if ( player->priv->terminate )
-	return;
-	
-    player->priv->reload = FALSE;
-    player->priv->finished = FALSE;
-    parole_gst_play_uri (player->priv->gst, player->priv->url, NULL);
-}
-
 void parole_plugin_player_exit (ParolePluginPlayer *player)
 {
     player->priv->terminate = TRUE;
@@ -878,6 +899,10 @@ static gboolean parole_plugin_player_dbus_stop (ParolePluginPlayer *player,
 static gboolean parole_plugin_player_dbus_ping (ParolePluginPlayer *player,
 						GError **error);
 
+static gboolean parole_plugin_player_dbus_play_url (ParolePluginPlayer *player,
+						    gchar *in_URL,
+						    GError **error);
+
 #include "org.parole.media.plugin.h"
 
 /*
@@ -931,3 +956,12 @@ static gboolean parole_plugin_player_dbus_ping (ParolePluginPlayer *player,
     return TRUE;
 }
 						
+static gboolean parole_plugin_player_dbus_play_url (ParolePluginPlayer *player,
+						    gchar *in_URL,
+						    GError **error)
+{
+    player->priv->url = g_strdup (in_URL);
+    g_debug ("Playing url=%s", in_URL);
+    g_idle_add ((GSourceFunc) parole_plugin_player_play_idle, player);
+    return TRUE;
+}
diff --git a/browser-plugin/media-plugin/parole-plugin-player.h b/browser-plugin/media-plugin/parole-plugin-player.h
index bc3d506..4ada19e 100644
--- a/browser-plugin/media-plugin/parole-plugin-player.h
+++ b/browser-plugin/media-plugin/parole-plugin-player.h
@@ -45,6 +45,8 @@ typedef struct
     
     void				(*exiting)			      (ParolePluginPlayer *player);
     
+    void				(*ready)			      (ParolePluginPlayer *player);
+    
 } ParolePluginPlayerClass;
 
 GType        				 parole_plugin_player_get_type        (void) G_GNUC_CONST;
@@ -52,8 +54,6 @@ GType        				 parole_plugin_player_get_type        (void) G_GNUC_CONST;
 ParolePluginPlayer       		*parole_plugin_player_new             (GtkWidget *plug,
 									       gchar *url);
 									       
-void					 parole_plugin_player_play	      (ParolePluginPlayer *player);
-
 void					 parole_plugin_player_exit 	      (ParolePluginPlayer *player);
 
 G_END_DECLS
diff --git a/browser-plugin/npp_gate.cpp b/browser-plugin/npp_gate.cpp
index e4ce7ad..239765c 100644
--- a/browser-plugin/npp_gate.cpp
+++ b/browser-plugin/npp_gate.cpp
@@ -197,7 +197,7 @@ int32 NPP_WriteReady(NPP instance, NPStream * stream)
     if (pPlugin == NULL)
         return NPERR_GENERIC_ERROR;
 
-    //rv = pPlugin->WriteReady(stream);
+    rv = pPlugin->WriteReady(stream);
 
     return rv;
 }
@@ -213,7 +213,7 @@ int32 NPP_Write(NPP instance, NPStream * stream, int32 offset, int32 len, void *
     if (pPlugin == NULL)
         return NPERR_GENERIC_ERROR;
 
-    //rv = pPlugin->Write(stream, offset, len, buffer);
+    rv = pPlugin->Write(stream, offset, len, buffer);
     return rv;
 }
 
@@ -236,6 +236,10 @@ void NPP_StreamAsFile(NPP instance, NPStream * stream, const char *fname)
 {
     if (instance == NULL)
         return;
+	
+    CPlugin *pPlugin = (CPlugin *) instance->pdata;
+    
+    pPlugin->StreamAsFile (stream, fname);
 }
 
 void NPP_Print(NPP instance, NPPrint * printInfo)
@@ -254,7 +258,7 @@ void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyD
     if (pPlugin == NULL)
         return;
 
-    //pPlugin->URLNotify(url, reason, notifyData);
+    pPlugin->URLNotify(url, reason, notifyData);
 
 }
 
diff --git a/browser-plugin/parole-plugin.c b/browser-plugin/parole-plugin.c
new file mode 100644
index 0000000..038beef
--- /dev/null
+++ b/browser-plugin/parole-plugin.c
@@ -0,0 +1,464 @@
+/*
+ * * 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-glib.h>
+
+#include <X11/Xlib.h>
+
+#include <gtk/gtk.h>
+
+#include <parole/parole.h>
+
+#include "parole-plugin.h"
+
+int32 STREAMBUFSIZE = 0x0FFFFFFF;
+
+static void parole_plugin_finalize   (GObject *object);
+
+struct _ParolePlugin
+{
+    GObject          parent;
+    
+    DBusGConnection *bus;
+    DBusGProxy      *proxy;
+    
+    Window	     window;
+    gchar           *url;
+    gchar           *tmp_file;
+    FILE            *cache;
+    GSList 	    *list;
+    
+    gulong	     ping_id;
+    gboolean	     window_set;
+    gboolean	     is_playlist;
+    gboolean         checked;
+    gboolean	     player_ready;
+    gboolean	     player_started;
+    gboolean	     player_spawned;
+    gboolean	     player_exited;
+    gboolean	     player_playing;
+};
+
+struct _ParolePluginClass
+{
+    GObjectClass     parent_class;
+};
+
+G_DEFINE_TYPE (ParolePlugin, parole_plugin, G_TYPE_OBJECT)
+
+static void
+parole_plugin_class_init (ParolePluginClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_plugin_finalize;
+}
+
+static void
+parole_plugin_init (ParolePlugin *plugin)
+{
+    GError *error = NULL;
+    
+    plugin->proxy          = NULL;
+    plugin->url            = NULL;
+    plugin->cache          = NULL;
+    plugin->tmp_file       = NULL;
+    plugin->list           = NULL;
+    
+    plugin->window_set     = FALSE;
+    plugin->is_playlist    = FALSE;
+    plugin->checked        = FALSE;
+    plugin->player_ready   = FALSE;
+    plugin->player_started = FALSE;
+    plugin->player_spawned = FALSE;
+    plugin->player_exited  = FALSE;
+    plugin->player_playing = FALSE;
+    plugin->ping_id        = 0;
+    
+    plugin->bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+    
+    if ( error )
+    {
+	g_warning ("Failed to get session bus %s", error->message);
+	g_error_free (error);
+    }
+}
+
+static gboolean
+parole_plugin_ping (gpointer data)
+{
+    ParolePlugin *plugin;
+    
+    plugin = PAROLE_PLUGIN (data);
+    
+    dbus_g_proxy_call_no_reply  (plugin->proxy, "Ping",
+				 G_TYPE_INVALID,
+				 G_TYPE_INVALID);
+    return TRUE;
+}
+
+
+static void
+parole_plugin_player_exiting_cb (DBusGProxy *proxy, ParolePlugin *plugin)
+{
+    g_debug ("Player exiting");
+    plugin->player_exited = TRUE;
+    if ( plugin->ping_id != 0 )
+	g_source_remove (plugin->ping_id);
+}
+
+static void
+parole_plugin_player_ready_cb (DBusGProxy *proxy, ParolePlugin *plugin)
+{
+    g_debug ("Player ready");
+    plugin->player_ready = TRUE;
+    
+    if ( plugin->ping_id == 0 )
+    {
+	plugin->ping_id = g_timeout_add_seconds (10, (GSourceFunc) parole_plugin_ping, plugin);
+    }
+}
+
+static void
+parole_plugin_stop_player (ParolePlugin *plugin)
+{
+    g_return_if_fail (plugin->proxy != NULL);
+    
+    if ( plugin->player_ready || plugin->player_spawned )
+    {
+	gint num_tries = 0;
+	
+	do
+	{
+	    GError *error = NULL;
+	    g_debug ("Sending Quit message");
+	    dbus_g_proxy_call (plugin->proxy, "Quit", &error,
+			       G_TYPE_INVALID,
+			       G_TYPE_INVALID);
+		
+	    /*
+	     * This might happen if the browser unload the plugin quickly
+	     * while the process didn't get the dbus name.
+	     */
+	    if ( error )
+	    {
+#ifdef DEBUG
+		g_debug ("Failed to stop the backend via D-Bus %s", error->message);
+#endif
+		if ( g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NO_REPLY ) ||
+		     g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN) )
+		{
+		    g_error_free (error);
+		    g_main_context_iteration(NULL, FALSE);
+		    g_usleep (100000);
+		    num_tries++;
+		    g_debug ("No reply, probably not ready, re-trying");
+		}
+		else
+		    break;
+	    }
+	    else
+		break;
+	    
+	} while (num_tries  < 4  && plugin->player_exited != TRUE);
+    }
+}
+
+static void
+parole_plugin_finalize (GObject *object)
+{
+    ParolePlugin *plugin;
+
+    plugin = PAROLE_PLUGIN (object);
+    
+    if ( plugin->ping_id != 0 )
+	g_source_remove (plugin->ping_id);
+    
+    parole_plugin_stop_player (plugin);
+    
+    if ( plugin->tmp_file )
+    {
+	remove (plugin->tmp_file);
+	g_free (plugin->tmp_file);
+    }
+    
+    if ( plugin->cache )
+	fclose (plugin->cache);
+    
+    if ( plugin->bus )
+	dbus_g_connection_unref (plugin->bus);
+
+    if ( plugin->url )
+	g_free (plugin->url);
+
+    if ( plugin->proxy )
+    {
+	dbus_g_proxy_disconnect_signal (plugin->proxy, "Exiting",
+				        G_CALLBACK (parole_plugin_player_exiting_cb), plugin);
+				     
+	dbus_g_proxy_disconnect_signal (plugin->proxy, "Ready",
+				        G_CALLBACK (parole_plugin_player_ready_cb), plugin);
+				       
+	g_object_unref (plugin->proxy);
+    }
+
+    G_OBJECT_CLASS (parole_plugin_parent_class)->finalize (object);
+}
+
+static void
+parole_plugin_get_proxy (ParolePlugin *plugin)
+{
+    gchar *dbus_name;
+    
+    g_return_if_fail (plugin->bus != NULL);
+    
+    dbus_name = g_strdup_printf ("org.Parole.Media.Plugin%ld", plugin->window);
+    
+    plugin->proxy = dbus_g_proxy_new_for_name (plugin->bus, 
+					       dbus_name,
+					       "/org/Parole/Media/Plugin",
+					        "org.Parole.Media.Plugin");
+    
+    if ( plugin->proxy == NULL) 
+	g_critical ("Unable to create proxy for %s", dbus_name);
+    else
+    {
+	dbus_g_proxy_add_signal (plugin->proxy, "Exiting", G_TYPE_INVALID);
+	dbus_g_proxy_add_signal (plugin->proxy, "Ready", G_TYPE_INVALID);
+	
+	dbus_g_proxy_connect_signal (plugin->proxy, "Exiting",
+				     G_CALLBACK (parole_plugin_player_exiting_cb), plugin, NULL);
+				     
+	dbus_g_proxy_connect_signal (plugin->proxy, "Ready",
+				     G_CALLBACK (parole_plugin_player_ready_cb), plugin, NULL);
+    }
+}
+
+static NPError
+parole_plugin_run_player (ParolePlugin *plugin)
+{
+    gchar *command[4];
+    gchar *socket;
+    gchar *app;
+    GError *error = NULL;
+
+    socket = g_strdup_printf ("%ld", plugin->window);
+    
+    app = g_build_filename (LIBEXECDIR, "parole-media-plugin", NULL);
+
+    command[0] = app;
+    command[1] = (gchar *)"--socket-id";
+    command[2] = socket;
+    command[3] = NULL;
+
+    if ( !g_spawn_async (NULL, 
+			 command,
+			 NULL,
+			 (GSpawnFlags) 0,
+			 NULL, NULL,
+			 NULL, 
+			 &error) )
+    {
+	g_critical ("Failed to spawn command : %s", error->message);
+	g_error_free (error);
+	return NPERR_GENERIC_ERROR;
+    }
+
+    plugin->player_spawned = TRUE;
+
+    g_free (socket);
+    g_free (app);
+
+    parole_plugin_get_proxy (plugin);
+
+    return NPERR_NO_ERROR;
+}
+
+static void
+parole_plugin_send_play (ParolePlugin *plugin, const gchar *url)
+{
+    GError *error = NULL;
+    g_return_if_fail (plugin->proxy);
+    
+    g_debug ("Sending play request of stream %s", url);
+    dbus_g_proxy_call (plugin->proxy, "PlayUrl", &error,
+		       G_TYPE_STRING, url,
+		       G_TYPE_INVALID,
+		       G_TYPE_INVALID);
+		       
+    plugin->player_playing = TRUE;
+    
+    if ( error )
+    {
+	g_critical ("Failed to play stream %s : %s", url, error->message);
+	g_error_free (error);
+	plugin->player_playing = FALSE;
+    }
+}
+
+ParolePlugin *
+parole_plugin_new (void)
+{
+    ParolePlugin *plugin = NULL;
+    plugin = g_object_new (PAROLE_TYPE_PLUGIN, NULL);
+    return plugin;
+}
+
+NPError parole_plugin_set_window (ParolePlugin *plugin, NPWindow * aWindow)
+{
+    g_debug ("SetWindow");
+    
+    if ( aWindow == NULL )
+	return NPERR_NO_ERROR;
+    
+    if ( plugin->window_set == FALSE)
+    {
+	plugin->window = (Window) aWindow->window;
+	plugin->window_set = TRUE;
+	return parole_plugin_run_player (plugin);
+    }
+    
+    return NPERR_NO_ERROR;
+}
+
+NPError	parole_plugin_new_stream (ParolePlugin *plugin, NPStream *stream, NPMIMEType type)
+{
+    if ( plugin->url == NULL )
+    {
+	plugin->url = g_strdup (stream->url);
+	g_debug ("NewStream=%s", plugin->url);
+    }
+    
+    return NPERR_NO_ERROR;
+}
+
+NPError	parole_plugin_destroy_stream (ParolePlugin *plugin, NPStream * stream, NPError reason)
+{
+    if ( reason != NPRES_DONE )
+    {
+	g_debug ("Destroy stream %s reason %i ", stream->url, reason);
+	parole_plugin_shut (plugin);
+    }
+    
+    return NPERR_NO_ERROR;
+}
+
+void parole_plugin_shut	(ParolePlugin *plugin)
+{
+    g_debug ("Shut");
+    
+    if ( plugin->player_ready )
+    {
+	g_debug ("Sending Stop signal");
+        dbus_g_proxy_call_no_reply (plugin->proxy, "Stop",
+                                    G_TYPE_INVALID,
+                                    G_TYPE_INVALID);
+
+    }
+}
+
+void parole_plugin_url_notify (ParolePlugin *plugin, 
+			       const char *url, 
+			       NPReason reason, 
+			       void *notifyData)
+{
+    g_debug ("UrlNotify=%s reason=%i", url, reason);
+    
+}
+
+void parole_plugin_stream_as_file (ParolePlugin *plugin,
+				   NPStream *stream,
+				   const gchar *fname)
+{
+    g_debug ("StreamAsFile url=%s fname=%s", stream->url, fname);
+}
+
+int32 parole_plugin_write_ready	(ParolePlugin *plugin, NPStream *stream)
+{
+    g_debug ("WriteReady url=%s", stream->url);
+    
+    return  plugin->player_ready ? STREAMBUFSIZE  : 0;
+}
+								 
+int32 parole_plugin_write (ParolePlugin *plugin, 
+			   NPStream * stream, 
+			   int32 offset, 
+			   int32 len, 
+			   void *buffer)
+{
+    static int32 wrotebytes = -1;
+    
+    if ( plugin->checked == FALSE )
+    {
+	/* Check if the url is a playlist */
+	g_debug ("Checking if stream is a playlist");
+	plugin->is_playlist = parole_pl_parser_can_parse_data ((const guchar*) buffer, len);
+	
+	plugin->checked = TRUE;
+    }
+
+    if ( plugin->is_playlist )
+    {
+	plugin->tmp_file = g_strdup_printf ("/tmp/parole-plugin-player-%ld", plugin->window);
+	    
+	if (plugin->cache == NULL)
+	{
+	    plugin->cache = fopen (plugin->tmp_file, "w");
+	    g_warn_if_fail (plugin->cache != NULL);
+	}
+	
+	if ( plugin->cache )
+	{
+	    fseek (plugin->cache, offset, SEEK_SET);
+	    wrotebytes += fwrite (buffer, 1, len, plugin->cache);
+	    g_debug ("Wrotebytes=%d offset=%d data=%s", wrotebytes, offset, (gchar*)buffer);
+	}
+	
+	if ( wrotebytes >= 0 )
+	{
+	    ParoleFile *file;
+	    fclose (plugin->cache);
+	    plugin->cache = NULL;
+	    plugin->list = parole_pl_parser_load_file (plugin->tmp_file);
+	    
+	    if (plugin->list != NULL && g_slist_length (plugin->list) != 0 && plugin->player_playing == FALSE )
+	    {
+		file = g_slist_nth_data (plugin->list, 0);
+		parole_plugin_send_play (plugin, parole_file_get_uri (file));
+		return len;
+	    }
+	}
+    }
+    else if ( plugin->player_ready && plugin->player_playing == FALSE  )
+    {
+	parole_plugin_send_play (plugin, stream->url);
+	return len;
+    }
+    
+    return 0;
+}
diff --git a/browser-plugin/parole-plugin.h b/browser-plugin/parole-plugin.h
new file mode 100644
index 0000000..85e1afd
--- /dev/null
+++ b/browser-plugin/parole-plugin.h
@@ -0,0 +1,76 @@
+/*
+ * * 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 <npapi.h>
+#include <npruntime.h>
+#include "npupp.h"
+
+G_BEGIN_DECLS
+
+typedef struct _ParolePluginClass ParolePluginClass;
+typedef struct _ParolePlugin 	  ParolePlugin;
+
+#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))
+
+GType        			parole_plugin_get_type        	(void) G_GNUC_CONST;
+
+ParolePlugin   		       *parole_plugin_new             	(void);
+
+NPError				parole_plugin_set_window	(ParolePlugin *plugin,
+								 NPWindow * aWindow);
+
+NPError				parole_plugin_new_stream	(ParolePlugin *plugin,
+								 NPStream *stream,
+								 NPMIMEType type);
+
+NPError				parole_plugin_destroy_stream	(ParolePlugin *plugin,
+							         NPStream * stream, 
+								 NPError reason);
+
+void				parole_plugin_shut		(ParolePlugin *plugin);
+								 
+void			        parole_plugin_url_notify        (ParolePlugin *plugin,
+								 const char *url, 
+								 NPReason reason, 
+								 void *notifyData);
+
+void				parole_plugin_stream_as_file	(ParolePlugin *plugin,
+								 NPStream *stream,
+								 const gchar *fname);
+
+int32				parole_plugin_write_ready	(ParolePlugin *plugin,
+								 NPStream *stream);
+								 
+int32   			parole_plugin_write             (ParolePlugin *plugin,
+								 NPStream * stream, 
+								 int32 offset, 
+								 int32 len, 
+								 void *buffer);
+
+G_END_DECLS
+
+#endif /* __PAROLE_PLUGIN_H */
diff --git a/browser-plugin/plugin.cpp b/browser-plugin/plugin.cpp
index b68859c..0ae98f0 100644
--- a/browser-plugin/plugin.cpp
+++ b/browser-plugin/plugin.cpp
@@ -70,76 +70,15 @@ CPlugin::CPlugin (NPP pNPInstance)
 {
     g_debug ("Constructor");
     
+    plugin = parole_plugin_new ();
+    
     mInstance = pNPInstance;
     mInitialized = TRUE;
-    window_set = FALSE;
-    child_spawned = FALSE;
-    url = NULL;
-    bus = NULL;
-    proxy = NULL;
-    process_exiting = FALSE;
-}
-
-void CPlugin::StopPlayer()
-{
-    gint num_tries = 0;
-    
-    if ( !proxy )
-	GetProxy ();
-    
-    if ( proxy && !process_exiting)
-    {
-	do
-	{
-	    GError *error = NULL;
-	    g_debug ("Sending Quit message");
-	    dbus_g_proxy_call (proxy, "Quit", &error,
-			       G_TYPE_INVALID,
-			       G_TYPE_INVALID);
-		
-	    /*
-	     * This might happen if the browser unload the plugin quickly
-	     * while the process didn't get the dbus name.
-	     */
-	    if ( error )
-	    {
-#ifdef DEBUG
-		g_debug ("Failed to stop the backend via D-Bus %s", error->message);
-#endif
-		if ( g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NO_REPLY ) ||
-		     g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN) )
-		{
-		    g_error_free (error);
-		    g_main_context_iteration(NULL, FALSE);
-		    g_usleep (100000);
-		    num_tries++;
-		    g_debug ("No reply, probably not ready, re-trying");
-		}
-		else
-		    break;
-	    }
-	    else
-		break;
-	    
-	} while (num_tries  < 4  && process_exiting != TRUE);
-    }   
-    
 }
 
 CPlugin::~CPlugin()
 {
-    g_debug ("Destructor");
-    
-    if ( ping_id != 0 ) 
-	g_source_remove (ping_id);
-    
-    StopPlayer ();
-    
-    if ( bus )
-	dbus_g_connection_unref (bus);
-    
-    if ( url )
-	g_free (url);
+    g_object_unref (plugin);
     mInstance = NULL;
 }
 
@@ -148,7 +87,6 @@ NPBool CPlugin::init(NPWindow * pNPWindow)
     if (pNPWindow == NULL)
         return FALSE;
 
-    m_Window = pNPWindow;
     mInitialized = TRUE;
 
     return mInitialized;
@@ -156,34 +94,12 @@ NPBool CPlugin::init(NPWindow * pNPWindow)
 
 NPError CPlugin::SetWindow(NPWindow * aWindow)
 {
-    g_debug ("SetWindow");
-    
-    if ( aWindow == NULL )
-	return FALSE;
-
-    if ( !window_set )
-    {
-	window = (Window) aWindow->window;
-	
-	window_set = TRUE;
-    }
-    return NPERR_NO_ERROR;
+    return parole_plugin_set_window (plugin, aWindow);
 }
 
 void CPlugin::shut()
 {
-    g_debug ("shut");
-    
-    if ( !proxy )
-	GetProxy ();
-    
-    if ( proxy )
-    {
-	g_debug ("Sending Stop signal");
-        dbus_g_proxy_call_no_reply (proxy, "Stop",
-                                    G_TYPE_INVALID,
-                                    G_TYPE_INVALID);
-    }   
+    parole_plugin_shut (plugin);
 }
 
 NPBool CPlugin::isInitialized()
@@ -191,130 +107,32 @@ NPBool CPlugin::isInitialized()
     return mInitialized;
 }
 
-static gboolean
-ping_process (gpointer data)
+NPError CPlugin::NewStream (NPMIMEType type, NPStream * stream, NPBool seekable, uint16 * stype)
 {
-    DBusGProxy *proxy;
-    
-    proxy = (DBusGProxy *) data;
-    
-    dbus_g_proxy_call (proxy, "Ping",
-		       G_TYPE_INVALID,
-		       G_TYPE_INVALID);
-		       
-    return TRUE;
+    return parole_plugin_new_stream (plugin, stream, type);
 }
 
-
-static void
-process_exiting_cb (DBusGProxy *proxy, gpointer data)
+NPError CPlugin::DestroyStream(NPStream * stream, NPError reason)
 {
-    CPlugin *plugin;
-    
-    plugin = (CPlugin *) data;
-    g_debug ("Process exiting");
-    plugin->process_exiting = TRUE;
-    g_source_remove (plugin->ping_id);
-    plugin->ping_id = 0;
+    return parole_plugin_destroy_stream (plugin, stream, reason);
 }
 
-void CPlugin::GetProxy ()
+void CPlugin::URLNotify (const char *url, NPReason reason, void *notifyData)
 {
-    g_return_if_fail (proxy == NULL);
-    
-    if ( child_spawned )
-    {
-	g_return_if_fail (bus != NULL);
-	
-	gchar *dbus_name;
-	dbus_name = g_strdup_printf ("org.Parole.Media.Plugin%ld", window);
-    
-	proxy = dbus_g_proxy_new_for_name (bus, 
-					   dbus_name,
-					   "/org/Parole/Media/Plugin",
-					   "org.Parole.Media.Plugin");
-	if ( !proxy ) 
-	    g_critical ("Unable to create proxy for %s", dbus_name);
-	else
-	{
-	    dbus_g_proxy_add_signal (proxy, "exiting", G_TYPE_INVALID);
-	    dbus_g_proxy_connect_signal (proxy, "exiting",
-					 G_CALLBACK (process_exiting_cb), this, NULL);
-	}
-	
-	g_free (dbus_name);
-    }
+    parole_plugin_url_notify (plugin, url, reason, notifyData);
 }
 
-NPError CPlugin::NewStream(NPMIMEType type, NPStream * stream, NPBool seekable, uint16 * stype)
+void CPlugin::StreamAsFile  (NPStream * stream, const char *fname)
 {
-    g_debug ("New stream callback %s", stream->url);
-    
-    if ( !url )
-    {
-	gchar *command[6];
-	gchar *socket;
-	gchar *app;
-	GError *error = NULL;
-	
-	url = g_strdup (stream->url);
-	
-	socket = g_strdup_printf ("%ld", window);
-#ifdef PAROLE_ENABLE_DEBUG
-	app = g_strdup ("media-plugin/parole-media-plugin");
-#else
-	app = g_build_filename (LIBEXECDIR, "parole-media-plugin", NULL);
-#endif
-
-	command[0] = app;
-	command[1] = (gchar *)"--socket-id";
-	command[2] = socket;
-	command[3] = (gchar *)"--url";
-	command[4] = url;
-	command[5] = NULL;
-	
-	if ( !g_spawn_async (NULL, 
-			     command,
-			     NULL,
-			     (GSpawnFlags) 0,
-			     NULL, NULL,
-			     &child_pid, 
-			     &error) )
-	{
-	    g_critical ("Failed to spawn command : %s", error->message);
-	    g_error_free (error);
-	    return NPERR_GENERIC_ERROR;
-	}
-	
-	child_spawned = TRUE;
-	
-	g_free (socket);
-	g_free (app);
-	
-	bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
-    
-	if ( error )
-	{
-	    g_critical ("%s : ", error->message);
-	    g_error_free (error);
-	    return NPERR_GENERIC_ERROR;
-	}
-	
-	GetProxy ();
-	if ( proxy )
-	    ping_id = g_timeout_add_seconds (5, (GSourceFunc) ping_process, proxy);
-	
-    }
-    return NPERR_NO_ERROR;
+    parole_plugin_stream_as_file (plugin, stream, fname);
 }
 
-NPError CPlugin::DestroyStream(NPStream * stream, NPError reason)
+int32 CPlugin::WriteReady (NPStream * stream)
 {
-    if ( reason != NPRES_DONE )
-    {
-	g_debug ("Destroy stream %s reason %i ", stream->url, reason);
-	shut ();
-    }
+    return parole_plugin_write_ready (plugin, stream);
+}
     
-    return NPERR_NO_ERROR;
+int32 CPlugin::Write (NPStream * stream, int32 offset, int32 len, void *buffer)
+{
+    return parole_plugin_write (plugin, stream, offset, len, buffer);
 }
diff --git a/browser-plugin/plugin.h b/browser-plugin/plugin.h
index a89feb9..9a1bce1 100644
--- a/browser-plugin/plugin.h
+++ b/browser-plugin/plugin.h
@@ -42,18 +42,11 @@
 #include <config.h>
 #endif
 
-#include <npapi.h>
-#include <npruntime.h>
-#include "npupp.h"
-
 #include <X11/Xlib.h>
 
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
 #include <glib.h>
-#include <glib/gstdio.h>
-#include <glib/gi18n.h>
+
+#include "parole-plugin.h"
 
 class CPlugin {
   private:
@@ -69,32 +62,21 @@ class CPlugin {
     void 	shut	();
     NPBool 	isInitialized();
     
-    NPError GetValue (NPPVariable variable, void *value);
-    NPError SetWindow (NPWindow * aWindow);
-    NPError NewStream (NPMIMEType type, NPStream * stream, NPBool seekable, uint16 * stype);
-    NPError DestroyStream (NPStream * stream, NPError reason);
-    
+    NPError GetValue 	  (NPPVariable variable, void *value);
     
-    void	GetProxy ();
-    void	StopPlayer();
-    
-  private:
-    DBusGConnection *bus;
-    DBusGProxy      *proxy;
-    
-    gboolean         window_set;
-    gboolean         child_spawned;
-    gchar           *url;
-    Window           window;
-    GPid	     child_pid;
+    NPError SetWindow 	  (NPWindow * aWindow);
+    NPError NewStream     (NPMIMEType type, NPStream * stream, NPBool seekable, uint16 * stype);
+    NPError DestroyStream (NPStream * stream, NPError reason);
+    void    URLNotify     (const char *url, NPReason reason, void *notifyData);
+    void    StreamAsFile  (NPStream * stream, const char *fname);
+    int32   WriteReady    (NPStream * stream);
+    int32   Write         (NPStream * stream, int32 offset, int32 len, void *buffer);
     
   public:
+    ParolePlugin    *plugin;
     NPP mInstance;
     uint16 mode;
     gchar *mimetype;
-    gboolean process_exiting;
-    gulong	     ping_id;
-
 };
 
 #endif                          // __PLUGIN_H__
diff --git a/gst/parole-gst.c b/gst/parole-gst.c
index c83672e..660152b 100644
--- a/gst/parole-gst.c
+++ b/gst/parole-gst.c
@@ -1514,6 +1514,9 @@ parole_gst_terminate_internal (ParoleGst *gst, gboolean fade_sound)
 
     parole_window_busy_cursor (GTK_WIDGET (gst)->window);
     
+    if ( gst->priv->embedded )
+	goto out;
+    
     if ( fade_sound && gst->priv->state == GST_STATE_PLAYING && !playing_video )
     {
 	gdouble volume;
@@ -1534,6 +1537,7 @@ parole_gst_terminate_internal (ParoleGst *gst, gboolean fade_sound)
 	}
     }
     
+out:
     parole_gst_change_state (gst, GST_STATE_NULL);
 }
 
@@ -1738,7 +1742,6 @@ parole_gst_class_init (ParoleGstClass *klass)
 {
     GObjectClass *object_class = G_OBJECT_CLASS (klass);
     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-    g_debug ("Class init");
 
     object_class->finalize = parole_gst_finalize;
     object_class->constructed = parole_gst_constructed;
@@ -1832,7 +1835,7 @@ static void
 parole_gst_init (ParoleGst *gst)
 {
     gst->priv = PAROLE_GST_GET_PRIVATE (gst);
-    g_debug ("Init");
+
     gst->priv->state = GST_STATE_VOID_PENDING;
     gst->priv->target = GST_STATE_VOID_PENDING;
     gst->priv->media_state = PAROLE_MEDIA_STATE_STOPPED;
diff --git a/parole/Makefile.am b/parole/Makefile.am
index 229c7c6..86b9e2f 100644
--- a/parole/Makefile.am
+++ b/parole/Makefile.am
@@ -19,12 +19,19 @@ libparole_la_SOURCES =				\
 	parole-provider-plugin.c		\
 	parole-provider-player.c		\
 	parole-file.c				\
-	parole-stream.c
+	parole-stream.c				\
+	parole-pl-parser.c			\
+	parole-pl-parser.h			\
+	parole-filters.c			\
+	parole-filters.h			\
+	parole-debug.c				\
+	parole-debug.h
 
 libparole_la_CFLAGS =				\
 	$(GIO_CFLAGS)                           \
 	$(GTK_CFLAGS)				\
-	$(TAGLIBC_CFLAGS)
+	$(TAGLIBC_CFLAGS)			\
+	$(LIBXFCE4UTIL_CFLAGS)
 
 paroleincludedir =				\
 	$(includedir)/parole
@@ -52,7 +59,8 @@ parole-marshal.h: parole-marshal.list
 
 parole_glib_enum_headers =		\
 	parole-stream.h			\
-	parole-provider-player.h
+	parole-provider-player.h	\
+	parole-pl-parser.h
 
 parole-enum-types.h: stamp-enum-types.h
 	@true
@@ -72,6 +80,7 @@ parole-enum-types.c: $(parole_glib_enum_headers) Makefile
 		--fhead "#include \"parole-enum-types.h\"\n\n" \
 		--fhead "#include \"parole-stream.h\"\n\n" \
 		--fhead "#include \"parole-provider-player.h\"\n\n" \
+		--fhead "#include \"parole-pl-parser.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@\" }," \
diff --git a/src/parole-debug.c b/parole/parole-debug.c
similarity index 100%
rename from src/parole-debug.c
rename to parole/parole-debug.c
diff --git a/src/parole-debug.h b/parole/parole-debug.h
similarity index 100%
rename from src/parole-debug.h
rename to parole/parole-debug.h
diff --git a/parole/parole-filters.c b/parole/parole-filters.c
new file mode 100644
index 0000000..cbfab27
--- /dev/null
+++ b/parole/parole-filters.c
@@ -0,0 +1,148 @@
+/*
+ * * 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-pl-parser.h"
+#include "data/mime/parole-mime-types.h"
+
+static char *playlist_mime_types[] = {
+    "text/plain",
+    "audio/x-mpegurl",
+    "audio/playlist",
+    "audio/x-scpls",
+    "audio/x-ms-asx",
+    "application/xml",
+    "application/xspf+xml",
+};
+
+/*
+ * 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;
+}
+
+GtkFileFilter *parole_get_supported_files_filter (void)
+{
+    GtkFileFilter *filter;
+    guint i;
+    
+    filter = parole_get_supported_media_filter ();
+    
+    gtk_file_filter_set_name (filter, _("All supported files"));
+    
+    for ( i = 0; i < G_N_ELEMENTS (playlist_mime_types); i++)
+	gtk_file_filter_add_mime_type (filter, playlist_mime_types[i]);
+    
+    return filter;
+    
+}
+
+GtkFileFilter 	*parole_get_supported_playlist_filter	(void)
+{
+    GtkFileFilter *filter;
+    guint i;
+    
+    filter = gtk_file_filter_new ();
+    
+    gtk_file_filter_set_name (filter, _("Playlist files"));
+    
+    for ( i = 0; i < G_N_ELEMENTS (playlist_mime_types); i++)
+	gtk_file_filter_add_mime_type (filter, playlist_mime_types[i]);
+    
+    return filter;
+}
+
+gboolean parole_file_filter (GtkFileFilter *filter, ParoleFile *file)
+{
+    GtkFileFilterInfo filter_info;
+
+    gboolean ret;
+    
+    filter_info.display_name = parole_file_get_display_name (file);
+    filter_info.mime_type = parole_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;
+}
diff --git a/src/parole-filters.h b/parole/parole-filters.h
similarity index 91%
rename from src/parole-filters.h
rename to parole/parole-filters.h
index 389aa1a..f23f18f 100644
--- a/src/parole-filters.h
+++ b/parole/parole-filters.h
@@ -18,6 +18,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#if !defined (__PAROLE_H_INSIDE__) && !defined (PAROLE_COMPILATION)
+#error "Only <parole.h> can be included directly."
+#endif
+
 #ifndef __PAROLE_FILTERS_H
 #define __PAROLE_FILTERS_H
 
@@ -51,11 +55,6 @@ gboolean		 parole_file_filter			(GtkFileFilter *filter,
 
 ParoleFileFormat	 parole_file_guess_format		(ParoleFile *file);
 
-void			 parole_get_media_files			(GtkFileFilter *filter,
-								 const gchar *path,
-								 gboolean recursive,
-								 GSList **list);
-
 G_END_DECLS
 
 #endif /* PAROLE_FILTERS_H */
diff --git a/src/parole-pl-parser.c b/parole/parole-pl-parser.c
similarity index 88%
rename from src/parole-pl-parser.c
rename to parole/parole-pl-parser.c
index 6c05936..5e7db07 100644
--- a/src/parole-pl-parser.c
+++ b/parole/parole-pl-parser.c
@@ -45,7 +45,7 @@
 #include "parole-pl-parser.h"
 #include "parole-filters.h"
 #include "parole-debug.h"
-#include "enum-gtypes.h"
+#include "parole-enum-types.h"
 
 typedef struct
 {
@@ -254,8 +254,39 @@ parole_pl_parser_guess_format_from_extension (const gchar *filename)
 static ParolePlFormat
 parole_pl_parser_guess_format_from_data (const gchar *filename)
 {
+    GFile *file;
+    gchar *mime_type = NULL;
+    gchar *contents;
+    gboolean result_uncertain;
+    gsize size;
     
-    return PAROLE_PL_FORMAT_UNKNOWN;
+    ParolePlFormat format = PAROLE_PL_FORMAT_UNKNOWN;
+    
+    file = g_file_new_for_path (filename);
+
+    if ( !g_file_load_contents (file, NULL, &contents, &size, NULL, NULL ) )
+    {
+	g_debug ("Unable to load content of file=%s", filename);
+	goto out;
+    }
+
+    mime_type = g_content_type_guess (NULL, (const guchar*)contents, size,  &result_uncertain);
+    
+    
+    if ( mime_type && result_uncertain == FALSE )
+    {
+	g_debug ("mime_type %s", mime_type);
+	format = PAROLE_PL_FORMAT_PLAYLIST;
+    }
+    
+    g_free (contents);
+    
+out:
+    if ( mime_type )
+	g_free (mime_type);
+    
+    g_object_unref (file);
+    return format;
 }
 
 static GSList *
@@ -508,6 +539,33 @@ parole_pl_parser_parse (ParolePlFormat format, const gchar *filename)
     return list;
 }
 
+gboolean parole_pl_parser_can_parse_data (const guchar *data, gint len)
+{
+    gchar *mime_type;
+    gboolean result_uncertain;
+    gboolean result = FALSE;
+
+    mime_type = g_content_type_guess (NULL, data, len,  &result_uncertain);
+    
+    if ( mime_type && result_uncertain == FALSE )
+    {
+	GtkFileFilter *filter = g_object_ref_sink (parole_get_supported_playlist_filter ());
+	GtkFileFilterInfo filter_info;
+	g_debug ("Mime_type=%s", mime_type);
+	filter_info.mime_type = mime_type;
+    
+	filter_info.contains = GTK_FILE_FILTER_MIME_TYPE;
+    
+	result = gtk_file_filter_filter (filter, &filter_info);
+	g_object_unref (filter);
+    }
+    
+    if ( mime_type )
+	g_free (mime_type);
+    
+    return result;
+}
+
 GSList *parole_pl_parser_load_file (const gchar *filename)
 {
     ParolePlFormat format = PAROLE_PL_FORMAT_UNKNOWN;
@@ -517,19 +575,18 @@ GSList *parole_pl_parser_load_file (const gchar *filename)
     filter = parole_get_supported_playlist_filter ();
     g_object_ref_sink (filter);
     
-    if ( (format = parole_pl_parser_guess_format_from_extension (filename)) == PAROLE_PL_FORMAT_UNKNOWN)
-	if ( (format = parole_pl_parser_guess_format_from_data (filename)) == PAROLE_PL_FORMAT_UNKNOWN)
-	{
-	    g_debug ("Unable to guess playlist format of file : %s", filename);
-	    goto out;
-	}
-	    
-    PAROLE_DEBUG_ENUM_FULL (format, ENUM_GTYPE_PL_FORMAT, "playlist %s ", filename);
-    list = parole_pl_parser_parse (format, filename);
+    if ( (format = parole_pl_parser_guess_format_from_extension (filename)) != PAROLE_PL_FORMAT_UNKNOWN)
+    {
+	PAROLE_DEBUG_ENUM_FULL (format, PAROLE_ENUM_TYPE_PL_FORMAT, "playlist %s ", filename);
+	list = parole_pl_parser_parse (format, filename);
+    }
+    else if ( (format = parole_pl_parser_guess_format_from_data (filename)) != PAROLE_PL_FORMAT_UNKNOWN)
+    {
+	list = parole_pl_parser_parse_m3u (filename);
+	//list = g_list_concat (list, parole_pl_parser_p
+    }
 	
-out:
     g_object_unref (filter);
-    
     return list;
 }
 
@@ -633,7 +690,7 @@ gboolean parole_pl_parser_save_file (GSList *files, const gchar *filename, Parol
     FILE *f;
     gboolean ret_val;
 
-    PAROLE_DEBUG_ENUM_FULL (format, ENUM_GTYPE_PL_FORMAT, "Saving playlist %s ", filename);
+    PAROLE_DEBUG_ENUM_FULL (format, PAROLE_ENUM_TYPE_PL_FORMAT, "Saving playlist %s ", filename);
     
     f = fopen (filename, "w");
     
diff --git a/src/parole-pl-parser.h b/parole/parole-pl-parser.h
similarity index 84%
rename from src/parole-pl-parser.h
rename to parole/parole-pl-parser.h
index 281924e..5c8dd20 100644
--- a/src/parole-pl-parser.h
+++ b/parole/parole-pl-parser.h
@@ -18,6 +18,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#if !defined (__PAROLE_H_INSIDE__) && !defined (PAROLE_COMPILATION)
+#error "Only <parole.h> can be included directly."
+#endif
+
 #ifndef __PAROLE_PL_PARSER_H
 #define __PAROLE_PL_PARSER_H
 
@@ -31,12 +35,15 @@ typedef enum
     PAROLE_PL_FORMAT_M3U,
     PAROLE_PL_FORMAT_PLS,
     PAROLE_PL_FORMAT_ASX,
-    PAROLE_PL_FORMAT_XSPF
+    PAROLE_PL_FORMAT_XSPF,
+    PAROLE_PL_FORMAT_PLAYLIST
     
 } ParolePlFormat;
 
 ParolePlFormat		 parole_pl_parser_guess_format_from_extension   (const gchar *filename);
 
+gboolean		 parole_pl_parser_can_parse_data		(const guchar *data, gint len);
+
 GSList 			*parole_pl_parser_load_file		        (const gchar *filename);
 
 gboolean		 parole_pl_parser_save_file		        (GSList *files,
diff --git a/parole/parole.h.in b/parole/parole.h.in
index 19c5ad7..a84dcfe 100644
--- a/parole/parole.h.in
+++ b/parole/parole.h.in
@@ -29,6 +29,9 @@
 #include <parole/parole-provider-player.h>
 #include <parole/parole-file.h>
 #include <parole/parole-stream.h>
+#include <parole/parole-pl-parser.h>
+#include <parole/parole-filters.h>
+#include <parole/parole-debug.h>
 
 #define PAROLE_MAJOR_VERSION		@PAROLE_VERSION_MAJOR@
 #define PAROLE_MINOR_VERSION		@PAROLE_VERSION_MINOR@
diff --git a/src/Makefile.am b/src/Makefile.am
index e95a8df..973ef3a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,17 +35,14 @@ NOINST_HFILES =					\
 	parole-vis.h				\
 	parole-statusbar.h			\
 	parole-mediachooser.h			\
-	parole-filters.h			\
 	parole-conf.h				\
 	parole-conf-dialog.h			\
 	parole-rc-utils.h			\
 	parole-utils.h				\
 	parole-disc.h				\
 	parole-medialist.h			\
-	parole-debug.h				\
 	parole-plugins-manager.h		\
 	parole-module.h				\
-	parole-pl-parser.h			\
 	parole-about.h				\
 	parole-builder.h			\
 	parole-subtitle-encoding.h		\
@@ -64,16 +61,13 @@ parole_SOURCES =				\
 	parole-statusbar.c			\
 	parole-medialist.c			\
 	parole-mediachooser.c			\
-	parole-filters.c			\
 	parole-conf.c				\
 	parole-conf-dialog.c			\
 	parole-disc.c				\
 	parole-rc-utils.c			\
 	parole-utils.c				\
-	parole-debug.c				\
 	parole-plugins-manager.c		\
 	parole-module.c				\
-	parole-pl-parser.c			\
 	parole-about.c				\
 	parole-builder.c			\
 	parole-subtitle-encoding.c		\
@@ -99,7 +93,6 @@ parole_LDADD =					\
 	$(TAGLIBC_LIBS)
 	
 parole_glib_enum_headers =			\
-	parole-pl-parser.h			\
 	parole-conf.h				\
 	parole-button.h
 
@@ -131,7 +124,6 @@ stamp-enum-gtypes.h: $(parole_glib_enum_headers) Makefile
 enum-gtypes.c: $(parole_glib_enum_headers) Makefile
 	( cd $(srcdir) && glib-mkenums \
 		--fhead "#include \"enum-gtypes.h\"\n\n" \
-		--fhead "#include \"parole-pl-parser.h\"\n\n" \
 		--fhead "#include \"parole-conf.h\"\n\n" \
 		--fhead "#include \"parole-button.h\"\n\n" \
 		--fprod "\n/* enumerations from \"@filename@\" */" \
diff --git a/src/parole-filters.c b/src/parole-filters.c
deleted file mode 100644
index f59c778..0000000
--- a/src/parole-filters.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * * 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 "parole-pl-parser.h"
-#include "data/mime/parole-mime-types.h"
-
-static char *playlist_mime_types[] = {
-    "text/plain",
-    "audio/x-mpegurl",
-    "audio/playlist",
-    "audio/x-scpls",
-    "audio/x-ms-asx",
-    "application/xml",
-    "application/xspf+xml",
-};
-
-/*
- * 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;
-}
-
-GtkFileFilter *parole_get_supported_files_filter (void)
-{
-    GtkFileFilter *filter;
-    guint i;
-    
-    filter = parole_get_supported_media_filter ();
-    
-    gtk_file_filter_set_name (filter, _("All supported files"));
-    
-    for ( i = 0; i < G_N_ELEMENTS (playlist_mime_types); i++)
-	gtk_file_filter_add_mime_type (filter, playlist_mime_types[i]);
-    
-    return filter;
-    
-}
-
-GtkFileFilter 	*parole_get_supported_playlist_filter	(void)
-{
-    GtkFileFilter *filter;
-    guint i;
-    
-    filter = gtk_file_filter_new ();
-    
-    gtk_file_filter_set_name (filter, _("Playlist files"));
-    
-    for ( i = 0; i < G_N_ELEMENTS (playlist_mime_types); i++)
-	gtk_file_filter_add_mime_type (filter, playlist_mime_types[i]);
-    
-    return filter;
-}
-
-gboolean parole_file_filter (GtkFileFilter *filter, ParoleFile *file)
-{
-    GtkFileFilterInfo filter_info;
-
-    gboolean ret;
-    
-    filter_info.display_name = parole_file_get_display_name (file);
-    filter_info.mime_type = parole_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, 
-			     gboolean recursive, GSList **list)
-{
-    GtkFileFilter *playlist_filter;
-    GSList *list_internal = NULL;
-    GSList *playlist = NULL;
-    GDir *dir;
-    const gchar *name;
-    ParoleFile *file;
-
-    playlist_filter = parole_get_supported_playlist_filter ();
-    g_object_ref_sink (playlist_filter);
-
-    if ( g_file_test (path, G_FILE_TEST_IS_REGULAR ) )
-    {
-	file = parole_file_new (path);
-	if ( parole_file_filter (playlist_filter, file) && 
-	     parole_pl_parser_guess_format_from_extension (path) != PAROLE_PL_FORMAT_UNKNOWN )
-	{
-	    playlist = parole_pl_parser_load_file (path);
-	    g_object_unref (file);
-	    if ( playlist)
-	    {
-		*list = g_slist_concat (*list, playlist);
-	    }
-	}
-	else 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) && recursive)
-	    {
-		parole_get_media_files (filter, path_internal, TRUE, list);
-	    }
-	    else if ( g_file_test (path_internal, G_FILE_TEST_IS_REGULAR) )
-	    {
-		file = parole_file_new (path_internal);
-		if ( parole_file_filter (playlist_filter, file) &&
-		     parole_pl_parser_guess_format_from_extension (path) != PAROLE_PL_FORMAT_UNKNOWN)
-		{
-		    playlist = parole_pl_parser_load_file (path_internal);
-		    g_object_unref (file);
-		    if ( playlist)
-		    {
-			*list = g_slist_concat (*list, playlist);
-		    }
-		}
-		else 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);
-    }
-    g_object_unref (playlist_filter);
-}
diff --git a/src/parole-utils.c b/src/parole-utils.c
index e429d65..112eb65 100644
--- a/src/parole-utils.c
+++ b/src/parole-utils.c
@@ -31,6 +31,8 @@
 
 #include <libxfce4util/libxfce4util.h>
 
+#include <parole/parole.h>
+
 #include "parole-utils.h"
 
 /* List from xine-lib's demux_sputext.c */
@@ -335,3 +337,79 @@ GdkPixbuf *parole_icon_load (const gchar *icon_name, gint size)
     return pix;
     
 }
+
+void parole_get_media_files (GtkFileFilter *filter, const gchar *path, 
+			     gboolean recursive, GSList **list)
+{
+    GtkFileFilter *playlist_filter;
+    GSList *list_internal = NULL;
+    GSList *playlist = NULL;
+    GDir *dir;
+    const gchar *name;
+    ParoleFile *file;
+
+    playlist_filter = parole_get_supported_playlist_filter ();
+    g_object_ref_sink (playlist_filter);
+
+    if ( g_file_test (path, G_FILE_TEST_IS_REGULAR ) )
+    {
+	file = parole_file_new (path);
+	if ( parole_file_filter (playlist_filter, file) && 
+	     parole_pl_parser_guess_format_from_extension (path) != PAROLE_PL_FORMAT_UNKNOWN )
+	{
+	    playlist = parole_pl_parser_load_file (path);
+	    g_object_unref (file);
+	    if ( playlist)
+	    {
+		*list = g_slist_concat (*list, playlist);
+	    }
+	}
+	else 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) && recursive)
+	    {
+		parole_get_media_files (filter, path_internal, TRUE, list);
+	    }
+	    else if ( g_file_test (path_internal, G_FILE_TEST_IS_REGULAR) )
+	    {
+		file = parole_file_new (path_internal);
+		if ( parole_file_filter (playlist_filter, file) &&
+		     parole_pl_parser_guess_format_from_extension (path) != PAROLE_PL_FORMAT_UNKNOWN)
+		{
+		    playlist = parole_pl_parser_load_file (path_internal);
+		    g_object_unref (file);
+		    if ( playlist)
+		    {
+			*list = g_slist_concat (*list, playlist);
+		    }
+		}
+		else 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);
+    }
+    g_object_unref (playlist_filter);
+}
diff --git a/src/parole-utils.h b/src/parole-utils.h
index a26d66d..a7e216e 100644
--- a/src/parole-utils.h
+++ b/src/parole-utils.h
@@ -39,4 +39,9 @@ gboolean	parole_is_uri_disc			(const gchar *uri);
 GdkPixbuf      *parole_icon_load			(const gchar *icon_name,
 							 gint size);
 
+void			 parole_get_media_files		(GtkFileFilter *filter,
+							 const gchar *path,
+							 gboolean recursive,
+							 GSList **list);
+
 #endif /* __PAROLE_UTILS_ */



More information about the Xfce4-commits mailing list