[Xfce4-commits] <parole:master> Get rid of the parole plugin GObject in the browser and use the c++ class only.
Ali Abdallah
noreply at xfce.org
Mon Nov 30 19:42:01 CET 2009
Updating branch refs/heads/master
to 7bc22c613223eb7747fa9bff595335eb8c81d690 (commit)
from 2d6c8febcf5396ac442823208cfd0460326ff388 (commit)
commit 7bc22c613223eb7747fa9bff595335eb8c81d690
Author: Ali Abdallah <aliov at xfce.org>
Date: Mon Nov 30 19:18:24 2009 +0100
Get rid of the parole plugin GObject in the browser and use the
c++ class only.
browser-plugin/Makefile.am | 9 +-
browser-plugin/media-plugin/Makefile.am | 7 +-
.../media-plugin/org.parole.media.plugin.xml | 4 +
browser-plugin/media-plugin/parole-plugin-player.c | 98 +++--
browser-plugin/media-plugin/parole-plugin-player.h | 4 -
browser-plugin/parole-plugin.c | 499 --------------------
browser-plugin/parole-plugin.h | 78 ---
browser-plugin/plugin.cpp | 369 ++++++++++++++-
browser-plugin/plugin.h | 33 ++-
gst/parole-gst.c | 3 +-
parole/parole-pl-parser.c | 10 +-
src/parole-plugins-manager.c | 13 +-
12 files changed, 477 insertions(+), 650 deletions(-)
diff --git a/browser-plugin/Makefile.am b/browser-plugin/Makefile.am
index 4a78bcc..eb8df91 100644
--- a/browser-plugin/Makefile.am
+++ b/browser-plugin/Makefile.am
@@ -22,15 +22,12 @@ 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)
@@ -41,8 +38,6 @@ 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 \
@@ -57,6 +52,4 @@ parole_player_so_LDFLAGS = \
-shared \
$(GTK_LIBS) \
$(DBUS_GLIB_LIBS) \
- $(TAGLIBC_LIBS) \
- $(LIBXFCE4UTIL_LIBS) \
- $(top_builddir)/parole/libparole.la
+ $(GECKO_LIBS)
diff --git a/browser-plugin/media-plugin/Makefile.am b/browser-plugin/media-plugin/Makefile.am
index 0ae092a..768d8dc 100644
--- a/browser-plugin/media-plugin/Makefile.am
+++ b/browser-plugin/media-plugin/Makefile.am
@@ -8,6 +8,7 @@ parole_media_plugin_SOURCES = \
parole_media_plugin_CFLAGS = \
-I$(top_srcdir) \
+ -I$(top_srcdir)/parole \
-I$(top_srcdir)/data \
-I$(top_srcdir)/data/mime \
-I$(top_srcdir)/dbus \
@@ -21,7 +22,8 @@ parole_media_plugin_CFLAGS = \
$(GST_VIDEO_CFLAGS) \
$(GST_INTERFACES_CFLAGS) \
$(DBUS_GLIB_CFLAGS) \
- $(LIBXFCE4GUI_CFLAGS)
+ $(LIBXFCE4GUI_CFLAGS) \
+ $(TAGLIBC_CFLAGS)
parole_media_plugin_LDADD = \
$(top_builddir)/dbus/libparoledbus.la \
@@ -32,7 +34,8 @@ parole_media_plugin_LDADD = \
$(GST_VIDEO_LIBS) \
$(GST_INTERFACES_LIBS) \
$(DBUS_GLIB_LIBS) \
- $(LIBXFCE4GUI_LIBS)
+ $(LIBXFCE4GUI_LIBS) \
+ $(TAGLIBC_LIBS)
if MAINTAINER_MODE
diff --git a/browser-plugin/media-plugin/org.parole.media.plugin.xml b/browser-plugin/media-plugin/org.parole.media.plugin.xml
index abcdb9a..c3a2a30 100644
--- a/browser-plugin/media-plugin/org.parole.media.plugin.xml
+++ b/browser-plugin/media-plugin/org.parole.media.plugin.xml
@@ -18,6 +18,10 @@
<arg type="s" name="url" direction="in"/>
</method>
+ <method name="PlayList">
+ <arg type="s" name="list" direction="in"/>
+ </method>
+
<signal name="Error">
</signal>
diff --git a/browser-plugin/media-plugin/parole-plugin-player.c b/browser-plugin/media-plugin/parole-plugin-player.c
index 183cdf3..103bdee 100644
--- a/browser-plugin/media-plugin/parole-plugin-player.c
+++ b/browser-plugin/media-plugin/parole-plugin-player.c
@@ -28,6 +28,8 @@
#include <gdk/gdkkeysyms.h>
+#include <parole/parole.h>
+
#include <libxfce4util/libxfce4util.h>
#include "parole-plugin-player.h"
@@ -75,13 +77,15 @@ struct ParolePluginPlayerPrivate
GtkWidget *volume;
GtkWidget *buffering;
+ GSList *list;
+
ParoleScreenSaver *saver;
ParoleMediaState state;
gboolean fullscreen;
- gboolean reload;
+ gboolean reload;
gboolean internal_range_change;
gboolean user_seeking;
gboolean terminate;
@@ -99,8 +103,6 @@ enum
enum
{
- SIG_ERROR,
- SIG_FINISHED,
SIG_EXITING,
SIG_READY,
LAST_SIGNAL
@@ -116,7 +118,6 @@ 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);
}
@@ -236,10 +237,7 @@ parole_plugin_player_play_clicked_cb (ParolePluginPlayer *player)
else if ( player->priv->state == PAROLE_MEDIA_STATE_PAUSED )
parole_gst_resume (player->priv->gst);
else if ( player->priv->finished )
- {
- player->priv->reload = TRUE;
parole_gst_stop (PAROLE_GST (player->priv->gst));
- }
}
static void
@@ -303,26 +301,49 @@ parole_plugin_player_media_state_cb (ParoleGst *gst, const ParoleStream *stream,
}
else if ( state == PAROLE_MEDIA_STATE_STOPPED )
{
+ parole_plugin_player_change_range_value (player, 0);
+
if ( player->priv->terminate )
{
gtk_main_quit ();
}
- parole_plugin_player_change_range_value (player, 0);
-
- if ( player->priv->reload )
+ else if ( player->priv->reload )
+ {
+ player->priv->reload = FALSE;
+ parole_plugin_player_play (player);
+ }
+ /* Play next item */
+ else if ( player->priv->list != NULL && player->priv->url )
{
parole_plugin_player_play (player);
}
else if ( player->priv->finished )
{
player->priv->finished = FALSE;
- g_signal_emit (player, signals [SIG_FINISHED], 0);
}
}
else if ( state == PAROLE_MEDIA_STATE_FINISHED )
{
parole_plugin_player_change_range_value (player, 0);
player->priv->finished = TRUE;
+
+ if ( player->priv->url )
+ {
+ g_free (player->priv->url);
+ player->priv->url = NULL;
+ }
+
+ if ( player->priv->list )
+ {
+ player->priv->list = player->priv->list->next;
+ if ( player->priv->list->data )
+ {
+ ParoleFile *file = NULL;
+ file = PAROLE_FILE (player->priv->list->data);
+ if ( file )
+ player->priv->url = g_strdup (parole_file_get_uri (file));
+ }
+ }
parole_gst_stop (PAROLE_GST (player->priv->gst));
}
}
@@ -392,8 +413,8 @@ parole_plugin_player_media_progressed_cb (ParoleGst *gst, const ParoleStream *st
static void
parole_plugin_player_reload (ParolePluginPlayer *player)
{
- parole_gst_stop (player->priv->gst);
player->priv->reload = TRUE;
+ parole_gst_stop (player->priv->gst);
}
static void
@@ -526,7 +547,6 @@ static gpointer *check_idle_thread (gpointer data)
g_usleep (1000000);
if ( g_timer_elapsed (idle_timer, NULL ) > 60.f )
{
- g_signal_emit (player, signals [SIG_EXITING], 0);
gtk_main_quit ();
}
@@ -542,8 +562,6 @@ parole_plugin_player_dispose (GObject *object)
player = PAROLE_PLUGIN_PLAYER (object);
- g_signal_emit (player, signals [SIG_EXITING], 0);
-
G_OBJECT_CLASS (parole_plugin_player_parent_class)->dispose (object);
}
@@ -743,24 +761,6 @@ parole_plugin_player_class_init (ParolePluginPlayerClass *klass)
object_class->constructed = parole_plugin_player_construct;
- signals[SIG_ERROR] =
- g_signal_new ("error",
- PAROLE_TYPE_PLUGIN_PLAYER,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ParolePluginPlayerClass, error),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0, G_TYPE_NONE);
-
- signals[SIG_FINISHED] =
- g_signal_new ("finished",
- PAROLE_TYPE_PLUGIN_PLAYER,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ParolePluginPlayerClass, finished),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0, G_TYPE_NONE);
-
signals[SIG_EXITING] =
g_signal_new ("exiting",
PAROLE_TYPE_PLUGIN_PLAYER,
@@ -814,10 +814,11 @@ parole_plugin_player_init (ParolePluginPlayer *player)
player->priv->saver = parole_screen_saver_new ();
player->priv->plug = NULL;
player->priv->fullscreen = FALSE;
- player->priv->reload = FALSE;
player->priv->terminate = FALSE;
+ player->priv->reload = FALSE;
player->priv->user_seeking = FALSE;
player->priv->internal_range_change = FALSE;
+ player->priv->list = NULL;
player->priv->state = PAROLE_MEDIA_STATE_STOPPED;
player->priv->gst = PAROLE_GST (parole_gst_new (TRUE, NULL));
@@ -901,6 +902,12 @@ parole_plugin_player_finalize (GObject *object)
if ( player->priv->url )
g_free (player->priv->url);
+ if ( player->priv->list )
+ {
+ g_slist_foreach (player->priv->list, (GFunc) g_object_unref, NULL);
+ g_slist_free (player->priv->list);
+ }
+
G_OBJECT_CLASS (parole_plugin_player_parent_class)->finalize (object);
}
@@ -973,6 +980,10 @@ static gboolean parole_plugin_player_dbus_play_url (ParolePluginPlayer *player,
gchar *in_URL,
GError **error);
+static gboolean parole_plugin_player_dbus_play_list (ParolePluginPlayer *player,
+ gchar *list,
+ GError **error);
+
#include "org.parole.media.plugin.h"
/*
@@ -1035,3 +1046,22 @@ static gboolean parole_plugin_player_dbus_play_url (ParolePluginPlayer *player,
g_idle_add ((GSourceFunc) parole_plugin_player_play_idle, player);
return TRUE;
}
+
+static gboolean parole_plugin_player_dbus_play_list (ParolePluginPlayer *player,
+ gchar *list,
+ GError **error)
+{
+ player->priv->list = parole_pl_parser_parse_from_file_by_extension (list);
+
+ if ( player->priv->list != NULL && g_slist_length (player->priv->list) != 0 )
+ {
+ ParoleFile *file;
+ file = g_slist_nth_data (player->priv->list, 0);
+
+ player->priv->url = g_strdup (parole_file_get_uri (file));
+ g_debug ("Playing url=%s", player->priv->url);
+ g_idle_add ((GSourceFunc) parole_plugin_player_play_idle, player);
+ }
+
+ return TRUE;
+}
diff --git a/browser-plugin/media-plugin/parole-plugin-player.h b/browser-plugin/media-plugin/parole-plugin-player.h
index e154ec8..4ada19e 100644
--- a/browser-plugin/media-plugin/parole-plugin-player.h
+++ b/browser-plugin/media-plugin/parole-plugin-player.h
@@ -43,10 +43,6 @@ typedef struct
{
GObjectClass parent_class;
- void (*error) (ParolePluginPlayer *player);
-
- void (*finished) (ParolePluginPlayer *player);
-
void (*exiting) (ParolePluginPlayer *player);
void (*ready) (ParolePluginPlayer *player);
diff --git a/browser-plugin/parole-plugin.c b/browser-plugin/parole-plugin.c
deleted file mode 100644
index 30e8609..0000000
--- a/browser-plugin/parole-plugin.c
+++ /dev/null
@@ -1,499 +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 <dbus/dbus-glib.h>
-
-#include <X11/Xlib.h>
-
-#include <gtk/gtk.h>
-
-#include <parole/parole.h>
-
-#include "parole-plugin.h"
-
-static int32_t STREAMBUFSIZE = 0x0FFFFFFF;
-
-static void parole_plugin_finalize (GObject *object);
-
-struct _ParolePlugin
-{
- GObject parent;
-
- DBusGConnection *bus;
- DBusGProxy *proxy;
-
- NPP Instance;
- 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_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;
- }
-}
-
-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_player_finished_cb (DBusGProxy *proxy, ParolePlugin *plugin)
-{
- g_debug ("Player finished");
- if ( plugin->is_playlist )
- {
- plugin->list = plugin->list->next;
- if ( plugin->list->data )
- {
- ParoleFile *file;
- file = PAROLE_FILE (plugin->list->data);
- parole_plugin_send_play (plugin, parole_file_get_uri (file));
- }
- }
-}
-
-static void
-parole_plugin_player_error_cb (DBusGProxy *proxy, ParolePlugin *plugin)
-{
- parole_plugin_player_finished_cb (NULL, 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, "Error", G_TYPE_INVALID);
- dbus_g_proxy_add_signal (plugin->proxy, "Finished", G_TYPE_INVALID);
- 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, "Error",
- G_CALLBACK (parole_plugin_player_error_cb), plugin, NULL);
-
- dbus_g_proxy_connect_signal (plugin->proxy, "Finished",
- G_CALLBACK (parole_plugin_player_finished_cb), plugin, NULL);
-
- 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;
-}
-
-ParolePlugin *
-parole_plugin_new (NPP Instance)
-{
- ParolePlugin *plugin = NULL;
- plugin = g_object_new (PAROLE_TYPE_PLUGIN, NULL);
- plugin->Instance = Instance;
- 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)
-{
- g_debug ("Destroy stream %s reason %i", stream->url, reason);
-
- 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_t parole_plugin_write_ready (ParolePlugin *plugin, NPStream *stream)
-{
- g_debug ("WriteReady url=%s", stream->url);
-
- if (plugin->checked)
- {
- NPN_DestroyStream (plugin->Instance, stream, NPRES_DONE);
- return -1;
- }
-
- return plugin->player_ready ? STREAMBUFSIZE : 0;
-}
-
-int32_t parole_plugin_write (ParolePlugin *plugin,
- NPStream * stream,
- int32_t offset,
- int32_t len,
- void *buffer)
-{
- static int32_t 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);
-#ifdef DEBUG
- g_debug ("Wrotebytes=%d offset=%d data=%s", wrotebytes, offset, (gchar*)buffer);
-#endif
- }
-
- if ( wrotebytes >= 0 )
- {
- ParoleFile *file;
- fclose (plugin->cache);
- plugin->cache = NULL;
- plugin->list = parole_pl_parser_parse_from_file_by_extension (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 wrotebytes;
-}
diff --git a/browser-plugin/parole-plugin.h b/browser-plugin/parole-plugin.h
deleted file mode 100644
index daee5a3..0000000
--- a/browser-plugin/parole-plugin.h
+++ /dev/null
@@ -1,78 +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
- */
-
-#ifndef __PAROLE_PLUGIN_H
-#define __PAROLE_PLUGIN_H
-
-#include <glib-object.h>
-
-#include <npapi.h>
-#include <npruntime.h>
-#include <npfunctions.h>
-
-#include <stdint.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 (NPP Instance);
-
-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_t parole_plugin_write_ready (ParolePlugin *plugin,
- NPStream *stream);
-
-int32_t parole_plugin_write (ParolePlugin *plugin,
- NPStream * stream,
- int32_t offset,
- int32_t len,
- void *buffer);
-
-G_END_DECLS
-
-#endif /* __PAROLE_PLUGIN_H */
diff --git a/browser-plugin/plugin.cpp b/browser-plugin/plugin.cpp
index d44104d..185a82d 100644
--- a/browser-plugin/plugin.cpp
+++ b/browser-plugin/plugin.cpp
@@ -39,6 +39,8 @@
#include "plugin_setup.h"
#include "plugin_types.h"
+static int32_t STREAMBUFSIZE = 0x0FFFFFFF;
+
NPError NS_PluginInitialize();
void NS_PluginShutdown();
NPError NS_PluginGetValue(NPPVariable aVariable, void *aValue);
@@ -62,6 +64,49 @@ NPError NS_PluginGetValue(NPPVariable aVariable, void *aValue)
return PluginGetValue(aVariable, aValue);
}
+
+//////////////////////
+/*
+ * Callbacks.
+ */
+static gboolean
+parole_plugin_ping (gpointer data)
+{
+ CPlugin *plugin = (CPlugin*)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, gpointer data)
+{
+ g_debug ("Player exiting");
+
+ CPlugin *plugin = (CPlugin*)data;
+
+ plugin->player_exited = TRUE;
+ if ( plugin->ping_id != 0 )
+ g_source_remove (plugin->ping_id);
+}
+
+static void
+parole_plugin_player_ready_cb (DBusGProxy *proxy, gpointer data)
+{
+ g_debug ("Player ready");
+
+ CPlugin *plugin = (CPlugin*)data;
+
+ plugin->player_ready = TRUE;
+
+ if ( plugin->ping_id == 0 )
+ {
+ plugin->ping_id = g_timeout_add_seconds (10, (GSourceFunc) parole_plugin_ping, plugin);
+ }
+}
+
////////////////////////////////////////
//
// CPlugin class implementation
@@ -70,15 +115,68 @@ CPlugin::CPlugin (NPP pNPInstance)
{
g_debug ("Constructor");
- plugin = parole_plugin_new (pNPInstance);
-
mInstance = pNPInstance;
mInitialized = TRUE;
+
+ GError *error = NULL;
+
+ proxy = NULL;
+ murl = NULL;
+ cache = NULL;
+ tmp_file = NULL;
+
+ window_set = FALSE;
+ is_playlist = FALSE;
+ checked = FALSE;
+ player_ready = FALSE;
+ player_started = FALSE;
+ player_spawned = FALSE;
+ player_exited = FALSE;
+ player_playing = FALSE;
+ ping_id = 0;
+
+ 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);
+ }
}
CPlugin::~CPlugin()
{
- g_object_unref (plugin);
+ if ( ping_id != 0 )
+ g_source_remove (ping_id);
+
+ StopPlayer ();
+
+ if ( tmp_file )
+ {
+ remove (tmp_file);
+ g_free (tmp_file);
+ }
+
+ if ( cache )
+ fclose (cache);
+
+ if ( bus )
+ dbus_g_connection_unref (bus);
+
+ if ( murl )
+ g_free (murl);
+
+ if ( proxy )
+ {
+ dbus_g_proxy_disconnect_signal (proxy, "Exiting",
+ G_CALLBACK (parole_plugin_player_exiting_cb), this);
+
+ dbus_g_proxy_disconnect_signal (proxy, "Ready",
+ G_CALLBACK (parole_plugin_player_ready_cb), this);
+
+ g_object_unref (proxy);
+ }
+
mInstance = NULL;
}
@@ -92,14 +190,148 @@ NPBool CPlugin::init(NPWindow * pNPWindow)
return mInitialized;
}
+void CPlugin::SendPlay (const gchar *url)
+{
+ GError *error = NULL;
+ g_return_if_fail (proxy);
+
+ g_debug ("Sending play request of stream %s", url);
+ dbus_g_proxy_call (proxy, "PlayUrl", &error,
+ G_TYPE_STRING, url,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+
+ player_playing = TRUE;
+
+ if ( error )
+ {
+ g_critical ("Failed to play stream %s : %s", url, error->message);
+ g_error_free (error);
+ player_playing = FALSE;
+ }
+}
+
+void
+CPlugin::SendList (const gchar *filename)
+{
+ GError *error = NULL;
+ g_return_if_fail (proxy);
+
+ g_debug ("Sending play request of playlist %s", filename);
+
+ dbus_g_proxy_call (proxy, "PlayList", &error,
+ G_TYPE_STRING, filename,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+
+ player_playing = TRUE;
+
+ if ( error )
+ {
+ g_critical ("Failed to play list %s : %s", filename, error->message);
+ g_error_free (error);
+ player_playing = FALSE;
+ }
+}
+
+NPError CPlugin::RunPlayer ()
+{
+ gchar *command[4];
+ gchar *socket;
+ gchar *app;
+ GError *error = NULL;
+
+ socket = g_strdup_printf ("%ld", 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;
+ }
+
+ player_spawned = TRUE;
+
+ g_free (socket);
+ g_free (app);
+
+ GetProxy ();
+
+ return NPERR_NO_ERROR;
+}
+
+void CPlugin::GetProxy ()
+{
+ gchar *dbus_name;
+
+ g_return_if_fail (bus != NULL);
+
+ 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 == NULL)
+ g_critical ("Unable to create proxy for %s", dbus_name);
+ else
+ {
+ dbus_g_proxy_add_signal (proxy, "Error", G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (proxy, "Finished", G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (proxy, "Exiting", G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (proxy, "Ready", G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal (proxy, "Exiting",
+ G_CALLBACK (parole_plugin_player_exiting_cb), this, NULL);
+
+ dbus_g_proxy_connect_signal (proxy, "Ready",
+ G_CALLBACK (parole_plugin_player_ready_cb), this, NULL);
+ }
+}
+
NPError CPlugin::SetWindow(NPWindow * aWindow)
{
- return parole_plugin_set_window (plugin, aWindow);
+ g_debug ("SetWindow");
+
+ if ( aWindow == NULL )
+ return NPERR_NO_ERROR;
+
+ if ( window_set == FALSE)
+ {
+ window = (Window) aWindow->window;
+ window_set = TRUE;
+ return RunPlayer ();
+ }
+
+ return NPERR_NO_ERROR;
}
void CPlugin::shut()
{
- parole_plugin_shut (plugin);
+ g_debug ("Shut");
+
+ if ( player_ready )
+ {
+ g_debug ("Sending Stop signal");
+ dbus_g_proxy_call_no_reply (proxy, "Stop",
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+
+ }
}
NPBool CPlugin::isInitialized()
@@ -107,32 +339,145 @@ NPBool CPlugin::isInitialized()
return mInitialized;
}
+void CPlugin::StopPlayer ()
+{
+ g_return_if_fail (proxy != NULL);
+
+ if ( player_ready || player_spawned )
+ {
+ gint num_tries = 0;
+
+ 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 && player_exited != TRUE);
+ }
+}
+
NPError CPlugin::NewStream (NPMIMEType type, NPStream * stream, NPBool seekable, uint16_t * stype)
{
- return parole_plugin_new_stream (plugin, stream, type);
+ if ( murl == NULL )
+ {
+ murl = g_strdup (stream->url);
+ g_debug ("NewStream=%s", murl);
+ }
+
+ return NPERR_NO_ERROR;
}
NPError CPlugin::DestroyStream(NPStream * stream, NPError reason)
{
- return parole_plugin_destroy_stream (plugin, stream, reason);
+ return NPERR_NO_ERROR;
}
void CPlugin::URLNotify (const char *url, NPReason reason, void *notifyData)
{
- parole_plugin_url_notify (plugin, url, reason, notifyData);
+ g_debug ("Url notify %s reason %i", url, reason);
}
-void CPlugin::StreamAsFile (NPStream * stream, const char *fname)
+void CPlugin::StreamAsFile (NPStream * stream, const char *fname)
{
- parole_plugin_stream_as_file (plugin, stream, fname);
+ g_debug ("StreamAsFile url=%s fname=%s", stream->url, fname);
}
int32_t CPlugin::WriteReady (NPStream * stream)
{
- return parole_plugin_write_ready (plugin, stream);
+ g_debug ("WriteReady url=%s", stream->url);
+
+ if (checked)
+ {
+ DestroyStream (stream, NPRES_DONE);
+ return -1;
+ }
+
+ return player_ready ? STREAMBUFSIZE : 0;
}
int32_t CPlugin::Write (NPStream * stream, int32_t offset, int32_t len, void *buffer)
{
- return parole_plugin_write (plugin, stream, offset, len, buffer);
+ static int32_t wrotebytes = -1;
+
+ if ( checked == FALSE )
+ {
+ gchar c;
+
+ /* Check if the url is a playlist */
+ g_debug ("Checking if stream is a playlist");
+ is_playlist = TRUE;
+ char *data = (char *) buffer;
+ for ( int32_t i = 0; i < len; i++)
+ {
+ c = data[i];
+ if ( g_ascii_iscntrl (c) && !g_ascii_isspace (c) )
+ {
+ is_playlist = FALSE;
+ break;
+ }
+ }
+ checked = TRUE;
+ }
+
+ if ( is_playlist )
+ {
+ tmp_file = g_strdup_printf ("/tmp/parole-plugin-player-%ld", window);
+
+ if (cache == NULL)
+ {
+ cache = fopen (tmp_file, "w");
+ g_warn_if_fail (cache != NULL);
+ }
+
+ if ( cache )
+ {
+ fseek (cache, offset, SEEK_SET);
+ wrotebytes += fwrite (buffer, 1, len, cache);
+#ifdef DEBUG
+ g_debug ("Wrotebytes=%d offset=%d data=%s", wrotebytes, offset, (gchar*)buffer);
+#endif
+ }
+
+ if ( wrotebytes >= 0 )
+ {
+ fclose (cache);
+ cache = NULL;
+
+ SendList (tmp_file);
+ }
+ }
+ else if ( player_ready && player_playing == FALSE )
+ {
+ SendPlay (stream->url);
+ return len;
+ }
+
+ return wrotebytes;
}
diff --git a/browser-plugin/plugin.h b/browser-plugin/plugin.h
index 29e0318..311ec1a 100644
--- a/browser-plugin/plugin.h
+++ b/browser-plugin/plugin.h
@@ -45,9 +45,14 @@
#include <X11/Xlib.h>
#include <glib.h>
+
+#include <npapi.h>
+#include <npruntime.h>
+#include <npfunctions.h>
+
#include <stdint.h>
-#include "parole-plugin.h"
+#include <dbus/dbus-glib.h>
class CPlugin {
private:
@@ -73,11 +78,35 @@ class CPlugin {
int32_t WriteReady (NPStream * stream);
int32_t Write (NPStream * stream, int32_t offset, int32_t len, void *buffer);
+ NPError RunPlayer (void);
+ void StopPlayer (void);
+ void GetProxy (void);
+ void SendPlay (const gchar *url);
+ void SendList (const gchar *filename);
+
+
public:
- ParolePlugin *plugin;
NPP mInstance;
uint16_t mode;
gchar *mimetype;
+
+ DBusGConnection *bus;
+ DBusGProxy *proxy;
+
+ Window window;
+ gchar *murl;
+ gchar *tmp_file;
+ FILE *cache;
+
+ 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;
};
#endif // __PLUGIN_H__
diff --git a/gst/parole-gst.c b/gst/parole-gst.c
index ca0c8e6..2dcace2 100644
--- a/gst/parole-gst.c
+++ b/gst/parole-gst.c
@@ -424,7 +424,7 @@ parole_gst_draw_logo_embedded (ParoleGstHelper *helper)
gst = PAROLE_GST (helper);
- if ( !gst->priv->terminating )
+ if ( gst->priv->terminating != TRUE )
parole_gst_draw_logo_common (gst);
}
@@ -912,6 +912,7 @@ parole_gst_evaluate_state (ParoleGst *gst, GstState old, GstState new, GstState
if ( gst->priv->target == new )
{
+ gtk_widget_queue_draw (GTK_WIDGET (gst));
parole_gst_set_window_cursor (GTK_WIDGET (gst)->window, NULL);
if ( gst->priv->state_change_id != 0 )
g_source_remove (gst->priv->state_change_id);
diff --git a/parole/parole-pl-parser.c b/parole/parole-pl-parser.c
index 9f61081..905b8a3 100644
--- a/parole/parole-pl-parser.c
+++ b/parole/parole-pl-parser.c
@@ -536,7 +536,7 @@ parole_pl_parser_parse (ParolePlFormat format, const gchar *filename)
gboolean parole_pl_parser_can_parse_data (const guchar *data, gint len)
{
- gchar *mime_type;
+ gchar *mime_type = NULL;
gboolean result_uncertain;
gboolean result = FALSE;
@@ -553,10 +553,8 @@ gboolean parole_pl_parser_can_parse_data (const guchar *data, gint len)
result = gtk_file_filter_filter (filter, &filter_info);
g_object_unref (filter);
- }
-
- if ( mime_type )
g_free (mime_type);
+ }
return result;
}
@@ -572,7 +570,7 @@ GSList *parole_pl_parser_parse_from_file_by_extension (const gchar *filename)
g_debug ("Unable to guess playlist format : %s", filename);
goto out;
}
-
+
PAROLE_DEBUG_ENUM_FULL (format, PAROLE_ENUM_TYPE_PL_FORMAT, "playlist %s ", filename);
list = parole_pl_parser_parse (format, filename);
@@ -693,7 +691,7 @@ gboolean parole_pl_parser_save_from_files (GSList *files, const gchar *filename,
gboolean ret_val;
PAROLE_DEBUG_ENUM_FULL (format, PAROLE_ENUM_TYPE_PL_FORMAT, "Saving playlist %s ", filename);
-
+
f = fopen (filename, "w");
switch (format)
diff --git a/src/parole-plugins-manager.c b/src/parole-plugins-manager.c
index f4cf6a1..d586eae 100644
--- a/src/parole-plugins-manager.c
+++ b/src/parole-plugins-manager.c
@@ -349,6 +349,7 @@ parole_plugins_manager_get_plugin_info (const gchar *desktop_file)
{
ParolePluginInfo *info;
GKeyFile *file;
+ GError *error = NULL;
info = g_new0 (ParolePluginInfo, 1);
@@ -359,9 +360,10 @@ parole_plugins_manager_get_plugin_info (const gchar *desktop_file)
file = g_key_file_new ();
- if ( !g_key_file_load_from_file (file, desktop_file , G_KEY_FILE_NONE, NULL) )
+ if ( !g_key_file_load_from_file (file, desktop_file , G_KEY_FILE_NONE, &error) )
{
- g_warning ("Error opening file : %s", desktop_file);
+ g_warning ("Error opening file : %s : %s", desktop_file, error->message);
+ g_error_free (error);
goto out;
}
@@ -535,14 +537,16 @@ static gchar *
parole_plugins_manager_get_module_name (const gchar *desktop_file)
{
GKeyFile *file;
+ GError *error = NULL;
gchar *module_name = NULL;
gchar *library_name = NULL;
file = g_key_file_new ();
- if ( !g_key_file_load_from_file (file, desktop_file, G_KEY_FILE_NONE, NULL) )
+ if ( !g_key_file_load_from_file (file, desktop_file, G_KEY_FILE_NONE, &error) )
{
- g_warning ("Error opening file : %s", desktop_file);
+ g_warning ("Error opening file : %s : %s", desktop_file, error->message);
+ g_error_free (error);
goto out;
}
@@ -726,6 +730,7 @@ void parole_plugins_manager_load (ParolePluginsManager *manager)
g_free (library_path);
continue;
}
+ TRACE ("Creating a module for %s desktop file %s", library_path, desktop_file);
module = parole_provider_module_new (library_path, desktop_file);
g_ptr_array_add (manager->priv->array, module);
More information about the Xfce4-commits
mailing list