[Xfce4-commits] <parole:master> Add some nice features from the new version, like media tooltips, open containing folder, media length.

Ali Abdallah noreply at xfce.org
Fri Apr 15 16:44:04 CEST 2011


Updating branch refs/heads/master
         to 6d95f5740234781afc222d6017728702d8bed5c0 (commit)
       from ef9b1bcc2ff829085dfc77e6bf53e650e26ce445 (commit)

commit 6d95f5740234781afc222d6017728702d8bed5c0
Author: Ali Abdallah <aliov at xfce.org>
Date:   Fri Apr 15 15:50:18 2011 +0200

    Add some nice features from the new version, like media tooltips, open
    containing folder, media length.

 common/parole-common.c      |   43 +++
 common/parole-common.h      |   11 +
 data/interfaces/playlist.ui |  261 +++++++++++--------
 src/parole-conf.c           |   80 ++++++-
 src/parole-conf.h           |    7 +-
 src/parole-mediachooser.c   |  212 +++++++++------
 src/parole-mediachooser.h   |   24 +--
 src/parole-medialist.c      |  616 ++++++++++++++++++++++++++++++++++++++++---
 src/parole-medialist.h      |   11 +-
 src/parole-open-location.c  |  107 +++-----
 src/parole-open-location.h  |   21 +--
 src/parole-utils.c          |   74 +++++
 src/parole-utils.h          |    4 +
 13 files changed, 1127 insertions(+), 344 deletions(-)

diff --git a/common/parole-common.c b/common/parole-common.c
index 695e919..424d70e 100644
--- a/common/parole-common.c
+++ b/common/parole-common.c
@@ -28,8 +28,51 @@
 
 #include <glib.h>
 
+#include <libxfce4util/libxfce4util.h>
+
 #include "parole-common.h"
 
+
+static void
+parole_dialog_show (GtkWindow *parent, 
+		    GtkMessageType type,
+		    const gchar *window_title,
+		    const gchar *title, 
+		    const gchar *msg)
+{
+    GtkWidget *dialog;
+    
+    dialog = gtk_message_dialog_new_with_markup (parent,
+						 GTK_DIALOG_DESTROY_WITH_PARENT,
+						 type,
+						 GTK_BUTTONS_CLOSE,
+						 "<span size='larger'><b>%s</b></span>",
+						 title);
+						 
+    gtk_window_set_title (GTK_WINDOW (dialog), window_title);
+    
+    gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (dialog), "%s", msg);
+
+
+    g_signal_connect_swapped (dialog,
+			      "response",
+			      G_CALLBACK (gtk_widget_destroy),
+			      dialog);
+
+    gtk_widget_show_all (dialog);
+}
+
+void parole_dialog_info	(GtkWindow *parent, const gchar *title,	const gchar *msg)
+{
+    parole_dialog_show (parent, GTK_MESSAGE_INFO, _("Message"), title, msg);
+}
+
+void parole_dialog_error (GtkWindow *parent, const gchar *title, const gchar *msg)
+{
+    parole_dialog_show (parent, GTK_MESSAGE_ERROR, _("Error"), title, msg);
+}
+
+
 void parole_window_busy_cursor		(GdkWindow *window)
 {
     GdkCursor *cursor;
diff --git a/common/parole-common.h b/common/parole-common.h
index 1cae844..3c12bfe 100644
--- a/common/parole-common.h
+++ b/common/parole-common.h
@@ -24,8 +24,19 @@
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 
+
+void		parole_dialog_info			(GtkWindow *parent,
+							 const gchar *title,
+							 const gchar *msg);
+
+void		parole_dialog_error			(GtkWindow *parent,
+							 const gchar *title,
+							 const gchar *msg);
+
 void		parole_window_busy_cursor		(GdkWindow *window);
 
 void		parole_window_invisible_cursor		(GdkWindow *window);
 
+
+
 #endif /* __PAROLE_COMMON_ */
diff --git a/data/interfaces/playlist.ui b/data/interfaces/playlist.ui
index 44304e7..3dc9f3e 100644
--- a/data/interfaces/playlist.ui
+++ b/data/interfaces/playlist.ui
@@ -1,135 +1,174 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy project-wide -->
-  <object class="GtkVBox" id="playlist-box">
-    <property name="visible">True</property>
-    <property name="orientation">vertical</property>
-    <property name="spacing">5</property>
-    <child>
-      <object class="GtkScrolledWindow" id="scrolledwindow1">
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="hscrollbar_policy">never</property>
-        <property name="vscrollbar_policy">automatic</property>
-        <property name="shadow_type">in</property>
-        <child>
-          <object class="GtkTreeView" id="media-list">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="headers_visible">False</property>
-            <property name="rules_hint">True</property>
-            <signal name="key_press_event" handler="parole_media_list_key_press"/>
-            <signal name="row_activated" handler="parole_media_list_row_activated_cb"/>
-            <signal name="button_release_event" handler="parole_media_list_button_release_event"/>
-            <signal name="drag_data_received" handler="parole_media_list_drag_data_received_cb"/>
-          </object>
-        </child>
-      </object>
-      <packing>
-        <property name="position">0</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkHBox" id="hbox3">
-        <property name="visible">True</property>
-        <property name="spacing">2</property>
-        <property name="homogeneous">True</property>
-        <child>
-          <object class="GtkButton" id="add-media">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="image">image1</property>
-            <signal name="clicked" handler="parole_media_list_add_clicked_cb"/>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButton" id="save-playlist">
-            <property name="visible">True</property>
-            <property name="sensitive">False</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="image">image5</property>
-            <signal name="clicked" handler="parole_media_list_save_cb"/>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButton" id="remove-media">
-            <property name="visible">True</property>
-            <property name="sensitive">False</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="image">image2</property>
-            <signal name="clicked" handler="parole_media_list_remove_clicked_cb"/>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButton" id="media-up">
-            <property name="visible">True</property>
-            <property name="sensitive">False</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="image">image3</property>
-            <signal name="clicked" handler="parole_media_list_media_up_clicked_cb"/>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">3</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButton" id="media-down">
-            <property name="visible">True</property>
-            <property name="sensitive">False</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="image">image4</property>
-            <signal name="clicked" handler="parole_media_list_media_down_clicked_cb"/>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="position">4</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">False</property>
-        <property name="position">1</property>
-      </packing>
-    </child>
-  </object>
   <object class="GtkImage" id="image1">
     <property name="visible">True</property>
+    <property name="can_focus">False</property>
     <property name="stock">gtk-add</property>
   </object>
   <object class="GtkImage" id="image2">
     <property name="visible">True</property>
+    <property name="can_focus">False</property>
     <property name="stock">gtk-remove</property>
   </object>
   <object class="GtkImage" id="image3">
     <property name="visible">True</property>
+    <property name="can_focus">False</property>
     <property name="stock">gtk-go-up</property>
   </object>
   <object class="GtkImage" id="image4">
     <property name="visible">True</property>
+    <property name="can_focus">False</property>
     <property name="stock">gtk-go-down</property>
   </object>
   <object class="GtkImage" id="image5">
     <property name="visible">True</property>
+    <property name="can_focus">False</property>
     <property name="stock">gtk-save-as</property>
   </object>
+  <object class="GtkVBox" id="playlist-box">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="spacing">5</property>
+    <child>
+      <object class="GtkAlignment" id="alignment1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <object class="GtkVBox" id="vbox1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkScrolledWindow" id="scrolledwindow1">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="hscrollbar_policy">never</property>
+                <property name="vscrollbar_policy">automatic</property>
+                <property name="window_placement_set">True</property>
+                <property name="shadow_type">in</property>
+                <child>
+                  <object class="GtkTreeView" id="media-list">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="has_tooltip">True</property>
+                    <property name="headers_visible">False</property>
+                    <property name="rules_hint">True</property>
+                    <signal name="key-press-event" handler="parole_media_list_key_press" swapped="no"/>
+                    <signal name="row-activated" handler="parole_media_list_row_activated_cb" swapped="no"/>
+                    <signal name="button-release-event" handler="parole_media_list_button_release_event" swapped="no"/>
+                    <signal name="drag-data-received" handler="parole_media_list_drag_data_received_cb" swapped="no"/>
+                    <signal name="query-tooltip" handler="parole_media_list_query_tooltip" swapped="no"/>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkHBox" id="hbox3">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="spacing">2</property>
+                <property name="homogeneous">True</property>
+                <child>
+                  <object class="GtkButton" id="add-media">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="image">image1</property>
+                    <signal name="clicked" handler="parole_media_list_add_clicked_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="save-playlist">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="image">image5</property>
+                    <signal name="clicked" handler="parole_media_list_save_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="remove-media">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="image">image2</property>
+                    <signal name="clicked" handler="parole_media_list_remove_clicked_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="media-up">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="image">image3</property>
+                    <signal name="clicked" handler="parole_media_list_media_up_clicked_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="media-down">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="image">image4</property>
+                    <signal name="clicked" handler="parole_media_list_media_down_clicked_cb" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">4</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="padding">4</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="expand">True</property>
+        <property name="fill">True</property>
+        <property name="position">0</property>
+      </packing>
+    </child>
+  </object>
 </interface>
diff --git a/src/parole-conf.c b/src/parole-conf.c
index 04bfce4..f5f1bbc 100644
--- a/src/parole-conf.c
+++ b/src/parole-conf.c
@@ -65,6 +65,13 @@ enum
     PROP_ASPECT_RATIO,
     PROP_WINDOW_WIDTH,
     PROP_WINDOW_HEIGHT,
+    PROP_MINIMIZED,
+    PROP_MULTIMEDIA_KEYS,
+    /*Playlist*/
+    PROP_REPLACE_PLAYLIST,
+    PROP_SCAN_FOLDER_RECURSIVELY,
+    PROP_START_PLAYING_OPENED_FILES,
+    PROP_REMOVE_DUPLICATED_PLAYLIST_ENTRIES,
     N_PROP
 };
 
@@ -242,6 +249,13 @@ parole_conf_class_init (ParoleConfClass *klass)
                                                            G_PARAM_READWRITE));
 							   
     g_object_class_install_property (object_class,
+                                     PROP_MINIMIZED,
+                                     g_param_spec_boolean ("minimized",
+                                                           NULL, NULL,
+                                                           FALSE,
+                                                           G_PARAM_READWRITE));
+							   
+    g_object_class_install_property (object_class,
                                      PROP_SUBTITLE_FONT,
                                      g_param_spec_string  ("subtitle-font",
                                                            NULL, NULL,
@@ -309,20 +323,62 @@ parole_conf_class_init (ParoleConfClass *klass)
                                      PROP_WINDOW_WIDTH,
                                      g_param_spec_int ("window-width",
                                                        NULL, NULL,
-                                                       320,
+                                                       100,
 						       G_MAXINT16,
-						       780,
+						       760,
                                                        G_PARAM_READWRITE));
 						       
     g_object_class_install_property (object_class,
                                      PROP_WINDOW_HEIGHT,
                                      g_param_spec_int ("window-height",
                                                        NULL, NULL,
-                                                       220,
+                                                       100,
 						       G_MAXINT16,
-						       480,
+						       420,
                                                        G_PARAM_READWRITE));
-						       
+    
+    g_object_class_install_property (object_class,
+                                     PROP_MULTIMEDIA_KEYS,
+                                     g_param_spec_boolean ("multimedia-keys",
+                                                           NULL, NULL,
+                                                           TRUE,
+                                                           G_PARAM_READWRITE));
+							   
+    /**
+     *Playlist options
+     **/
+    g_object_class_install_property (object_class,
+                                     PROP_REPLACE_PLAYLIST,
+                                     g_param_spec_boolean ("replace-playlist",
+                                                           NULL, NULL,
+                                                           FALSE,
+                                                           G_PARAM_READWRITE));
+    
+    g_object_class_install_property (object_class,
+                                     PROP_SCAN_FOLDER_RECURSIVELY,
+                                     g_param_spec_boolean ("scan-recursive",
+                                                           NULL, NULL,
+                                                           TRUE,
+                                                           G_PARAM_READWRITE));
+    
+    g_object_class_install_property (object_class,
+                                     PROP_START_PLAYING_OPENED_FILES,
+                                     g_param_spec_boolean ("play-opened-files",
+                                                           NULL, NULL,
+                                                           TRUE,
+                                                           G_PARAM_READWRITE));
+
+    /**
+     * 
+     * Remove duplicated entries from the playlist.
+     **/
+    g_object_class_install_property (object_class,
+                                     PROP_REMOVE_DUPLICATED_PLAYLIST_ENTRIES,
+                                     g_param_spec_boolean ("remove-duplicated",
+                                                           NULL, NULL,
+                                                           FALSE,
+                                                           G_PARAM_READWRITE));
+    
     g_type_class_add_private (klass, sizeof (ParoleConfPrivate));
 }
 
@@ -414,3 +470,17 @@ parole_conf_new (void)
 
     return PAROLE_CONF (parole_conf_object);
 }
+
+
+gboolean			 parole_conf_get_property_bool  (ParoleConf *conf,
+								 const gchar *name)
+{
+    gboolean value;
+    
+    g_object_get (G_OBJECT (conf),
+		  name, &value,
+		  NULL);
+		  
+    return value;
+}
+
diff --git a/src/parole-conf.h b/src/parole-conf.h
index 79910a2..73021aa 100644
--- a/src/parole-conf.h
+++ b/src/parole-conf.h
@@ -45,9 +45,12 @@ typedef struct
     
 } ParoleConfClass;
 
-GType        			 parole_conf_get_type        (void) G_GNUC_CONST;
+GType        			 parole_conf_get_type        	(void) G_GNUC_CONST;
 
-ParoleConf       		*parole_conf_new             (void);
+ParoleConf       		*parole_conf_new             	(void);
+
+gboolean			 parole_conf_get_property_bool  (ParoleConf *conf,
+								 const gchar *name);
 
 G_END_DECLS
 
diff --git a/src/parole-mediachooser.c b/src/parole-mediachooser.c
index c51fb79..098ec71 100644
--- a/src/parole-mediachooser.c
+++ b/src/parole-mediachooser.c
@@ -30,7 +30,6 @@
 #include <glib.h>
 
 #include <libxfce4util/libxfce4util.h>
-#include <libxfcegui4/libxfcegui4.h>
 
 #include <parole/parole-file.h>
 
@@ -44,15 +43,16 @@
 
 #include "common/parole-common.h"
 
-#include "gmarshal.h"
-
 /*
  * GtkBuilder Callbacks
  */
-void	parole_media_chooser_open 	(GtkWidget *widget, 
-				         ParoleMediaChooser *chooser);
+void    parole_media_chooser_add_clicked (GtkWidget *widget,
+					  ParoleMediaChooser *chooser);
+
+void    parole_media_chooser_close_clicked (GtkWidget *widget,
+					    ParoleMediaChooser *chooser);
 
-void	parole_media_chooser_close	(GtkWidget *widget,
+void	parole_media_chooser_destroy_cb (GtkWidget *widget,
 					 ParoleMediaChooser *chooser);
 					 
 void	media_chooser_folder_changed_cb (GtkWidget *widget, 
@@ -70,6 +70,24 @@ void    parole_media_chooser_replace_toggled_cb (GtkToggleButton *button,
 void    start_playing_toggled_cb (GtkToggleButton *button,
 				  gpointer data);
 
+struct ParoleMediaChooser
+{
+    GObject         		 parent;
+    
+    ParoleConf                  *conf;
+    GtkWidget			*window;
+    GtkWidget 			*info;
+    
+};
+
+struct ParoleMediaChooserClass
+{
+    GObjectClass 		 parent_class;
+    
+    void			 (*media_files_opened)		    (ParoleMediaChooser *chooser,
+								     GSList *list);
+};
+
 enum
 {
     MEDIA_FILES_OPENED,
@@ -78,12 +96,7 @@ enum
 
 static guint signals [LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (ParoleMediaChooser, parole_media_chooser, GTK_TYPE_DIALOG)
-
-void parole_media_chooser_close	(GtkWidget *widget, ParoleMediaChooser *chooser)
-{
-    gtk_widget_destroy (GTK_WIDGET (chooser));
-}
+G_DEFINE_TYPE (ParoleMediaChooser, parole_media_chooser, G_TYPE_OBJECT)
 
 void
 media_chooser_folder_changed_cb (GtkWidget *widget, gpointer data)
@@ -105,11 +118,7 @@ parole_media_chooser_add (ParoleMediaChooser *chooser, GtkWidget *file_chooser)
     GSList *files;
     GtkFileFilter *filter;
     GtkWidget *recursive;
-    GtkWidget *replace;
-    GtkWidget *play_opened;
     gboolean scan_recursive;
-    gboolean replace_playlist;
-    gboolean play;
     gchar *file;
     guint    i;
     guint len;
@@ -121,12 +130,8 @@ parole_media_chooser_add (ParoleMediaChooser *chooser, GtkWidget *file_chooser)
 	return;
 	
     recursive = g_object_get_data (G_OBJECT (chooser), "recursive");
-    replace = g_object_get_data (G_OBJECT (chooser), "replace-playlist");
-    play_opened = g_object_get_data (G_OBJECT (chooser), "play");
     
     scan_recursive = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (recursive));
-    replace_playlist = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (replace));
-    play = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (play_opened));
     
     len = g_slist_length (files);
     
@@ -136,63 +141,110 @@ parole_media_chooser_add (ParoleMediaChooser *chooser, GtkWidget *file_chooser)
 	parole_get_media_files (filter, file, scan_recursive, &media_files);
     }
     
-    g_signal_emit (G_OBJECT (chooser), signals [MEDIA_FILES_OPENED], 0, play, replace_playlist, media_files);
+    g_signal_emit (G_OBJECT (chooser), signals [MEDIA_FILES_OPENED], 0, media_files);
     g_slist_free (media_files);
     
     g_slist_foreach (files, (GFunc) g_free, NULL);
     g_slist_free (files);
 }
 
-void
-parole_media_chooser_open (GtkWidget *widget, ParoleMediaChooser *chooser)
+static gboolean
+parole_media_chooser_add_idle (gpointer data)
 {
+    ParoleMediaChooser *chooser;
     GtkWidget *file_chooser;
-
+    
+    chooser = PAROLE_MEDIA_CHOOSER (data);
+    
     file_chooser = GTK_WIDGET (g_object_get_data (G_OBJECT (chooser), "file-chooser"));
     
-    parole_window_busy_cursor (GTK_WIDGET (chooser)->window);
     parole_media_chooser_add (chooser, file_chooser);
-    gtk_widget_destroy (GTK_WIDGET (chooser));
+    
+    gtk_widget_destroy (chooser->window);
+    
+    return FALSE;
+}
+
+static void
+parole_media_chooser_open (ParoleMediaChooser *chooser)
+{
+    GtkWidget *img;
+    gchar *path;
+
+    parole_window_busy_cursor (chooser->window->window);
+    
+    path = g_build_filename (PIXMAPS_DIR, "loader.gif", NULL);
+    
+    img = gtk_image_new_from_file (path);
+    g_free (path);
+    
+    gtk_box_pack_start (GTK_BOX (chooser->info), img, FALSE, FALSE, 0);
+    gtk_widget_show_all (chooser->info);
+    
+    g_idle_add ((GSourceFunc) parole_media_chooser_add_idle, chooser);
+}
+
+void parole_media_chooser_add_clicked (GtkWidget *widget, ParoleMediaChooser *chooser)
+{
+    parole_media_chooser_open (chooser);
+}
+
+void parole_media_chooser_close_clicked (GtkWidget *widget, ParoleMediaChooser *chooser)
+{
+    gtk_widget_destroy (chooser->window);
+}
+
+void parole_media_chooser_destroy_cb (GtkWidget *widget, ParoleMediaChooser *chooser)
+{
+    g_object_unref (chooser);
 }
 
 void media_chooser_file_activate_cb (GtkFileChooser *filechooser, ParoleMediaChooser *chooser)
 {
-    parole_media_chooser_open (NULL, chooser);
+    parole_media_chooser_open (chooser);
 }
 
-void	parole_media_chooser_recursive_toggled_cb (GtkToggleButton *recursive,
-						   gpointer data)
+void parole_media_chooser_recursive_toggled_cb (GtkToggleButton *recursive,
+						gpointer data)
 {
-    parole_rc_write_entry_bool ("scan-recursive", 
-			        PAROLE_RC_GROUP_GENERAL, 
-				gtk_toggle_button_get_active (recursive));
+    ParoleMediaChooser *chooser;
+
+    chooser = PAROLE_MEDIA_CHOOSER (data);
+    
+    g_object_set (G_OBJECT (chooser->conf),
+		  "scan-recursive", gtk_toggle_button_get_active (recursive),
+		  NULL);
 }
 
 void    parole_media_chooser_replace_toggled_cb (GtkToggleButton *button,
 						 gpointer data)
 {
-    parole_rc_write_entry_bool ("replace-playlist", 
-			        PAROLE_RC_GROUP_GENERAL, 
-				gtk_toggle_button_get_active (button));
+    ParoleMediaChooser *chooser;
+
+    chooser = PAROLE_MEDIA_CHOOSER (data);
+    
+    g_object_set (G_OBJECT (chooser->conf),
+		  "replace-playlist", gtk_toggle_button_get_active (button),
+		  NULL);
 }
 
 void start_playing_toggled_cb (GtkToggleButton *button,
 			       gpointer data)
 {
-    parole_rc_write_entry_bool ("play-opened-files", 
-			        PAROLE_RC_GROUP_GENERAL, 
-				gtk_toggle_button_get_active (button));
+    ParoleMediaChooser *chooser;
+
+    chooser = PAROLE_MEDIA_CHOOSER (data);
+    
+    g_object_set (G_OBJECT (chooser->conf),
+		  "play-opened-files", gtk_toggle_button_get_active (button),
+		  NULL);
 }
 
 static void
-parole_media_chooser_open_internal (GtkWidget *chooser)
+parole_media_chooser_open_internal (ParoleMediaChooser *media_chooser)
 {
-    ParoleMediaChooser *media_chooser;
-    GtkWidget   *vbox;
     GtkWidget   *file_chooser;
     GtkBuilder  *builder;
-    GtkWidget   *open;
-    GtkWidget   *img;
     GtkWidget   *recursive;
     GtkWidget   *replace;
     GtkWidget   *play_opened;
@@ -201,17 +253,13 @@ parole_media_chooser_open_internal (GtkWidget *chooser)
     gboolean     play;
     const gchar *folder;
 
-    media_chooser = PAROLE_MEDIA_CHOOSER (chooser);
-    
     builder = parole_builder_new_from_string (mediachooser_ui, mediachooser_ui_length);
     
-    file_chooser = GTK_WIDGET (gtk_builder_get_object (builder, "filechooserwidget"));
+    media_chooser->window = GTK_WIDGET (gtk_builder_get_object (builder, "chooser"));
+    media_chooser->info = GTK_WIDGET (gtk_builder_get_object (builder, "info"));
     
-    vbox = GTK_WIDGET (gtk_builder_get_object (builder, "vbox"));
-    open = GTK_WIDGET (gtk_builder_get_object (builder, "open"));
+    file_chooser = GTK_WIDGET (gtk_builder_get_object (builder, "filechooserwidget"));
     
-    gtk_window_set_title (GTK_WINDOW (chooser), _("Add media files"));
-
     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), parole_get_supported_files_filter ());
     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), parole_get_supported_media_filter ());
     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), parole_get_supported_audio_filter ());
@@ -224,44 +272,41 @@ parole_media_chooser_open_internal (GtkWidget *chooser)
 	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_chooser), folder);
     
     gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (file_chooser), TRUE);
-    
-    scan_recursive = parole_rc_read_entry_bool ("scan-recursive", PAROLE_RC_GROUP_GENERAL, TRUE);
+
+    g_object_get (G_OBJECT (media_chooser->conf),
+		  "scan-recursive", &scan_recursive,
+		  "replace-playlist", &replace_playlist,
+		  "play-opened-files", &play,
+		  NULL);
     
     recursive = GTK_WIDGET (gtk_builder_get_object (builder, "recursive"));
     replace = GTK_WIDGET (gtk_builder_get_object (builder, "replace"));
     play_opened = GTK_WIDGET (gtk_builder_get_object (builder, "play-added-files"));
     
-    scan_recursive = parole_rc_read_entry_bool ("scan-recursive", PAROLE_RC_GROUP_GENERAL, TRUE);
-    replace_playlist = parole_rc_read_entry_bool ("replace-playlist", PAROLE_RC_GROUP_GENERAL, FALSE);
-    play = parole_rc_read_entry_bool ("play-opened-files", PAROLE_RC_GROUP_GENERAL, TRUE);
-    
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (recursive), scan_recursive);
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (replace), replace_playlist);
     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (play_opened), play);
     
-    img = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
-    
-    g_object_set (G_OBJECT (open),
-		  "image", img,
-		  "label", _("Add"),
-		  NULL);
+    g_object_set_data (G_OBJECT (media_chooser), "file-chooser", file_chooser);
+    g_object_set_data (G_OBJECT (media_chooser), "recursive", recursive);
     
-    g_object_set_data (G_OBJECT (chooser), "file-chooser", file_chooser);
-    g_object_set_data (G_OBJECT (chooser), "recursive", recursive);
-    g_object_set_data (G_OBJECT (chooser), "replace-playlist", replace);
-    g_object_set_data (G_OBJECT (chooser), "play", play_opened);
+    gtk_builder_connect_signals (builder, media_chooser);
     
-    gtk_container_add (GTK_CONTAINER (GTK_DIALOG (media_chooser)->vbox), vbox);
-    gtk_builder_connect_signals (builder, chooser);
-    g_signal_connect (chooser, "destroy",
-		      G_CALLBACK (gtk_widget_destroy), chooser);
-		      
     g_object_unref (builder);
 }
 
 static void
 parole_media_chooser_finalize (GObject *object)
 {
+    ParoleMediaChooser *chooser;
+    
+    chooser = PAROLE_MEDIA_CHOOSER (object);
+    
+    g_object_unref (chooser->conf);
+    
+    if ( chooser->window )
+	gtk_widget_destroy (chooser->window);
+    
     G_OBJECT_CLASS (parole_media_chooser_parent_class)->finalize (object);
 }
 
@@ -276,10 +321,8 @@ parole_media_chooser_class_init (ParoleMediaChooserClass *klass)
                       G_SIGNAL_RUN_LAST,
                       G_STRUCT_OFFSET (ParoleMediaChooserClass, media_files_opened),
                       NULL, NULL,
-		      _gmarshal_VOID__BOOLEAN_BOOLEAN_POINTER,
-                      G_TYPE_NONE, 3, 
-		      G_TYPE_BOOLEAN,
-		      G_TYPE_BOOLEAN,
+		      g_cclosure_marshal_VOID__POINTER,
+                      G_TYPE_NONE, 1, 
 		      G_TYPE_POINTER);
 
     object_class->finalize = parole_media_chooser_finalize;
@@ -288,22 +331,25 @@ parole_media_chooser_class_init (ParoleMediaChooserClass *klass)
 static void
 parole_media_chooser_init (ParoleMediaChooser *chooser)
 {
-    gtk_window_set_modal (GTK_WINDOW (chooser), TRUE);
+    chooser->conf = parole_conf_new ();
 }
 
-GtkWidget *parole_media_chooser_open_local (GtkWidget *parent)
+ParoleMediaChooser *parole_media_chooser_open_local (GtkWidget *parent)
 {
     ParoleMediaChooser *chooser;
         
     chooser = g_object_new (PAROLE_TYPE_MEDIA_CHOOSER, NULL);
     
+    parole_media_chooser_open_internal (chooser);
+
+    gtk_window_set_modal (GTK_WINDOW (chooser->window), TRUE);
+    
     if ( parent )
-	gtk_window_set_transient_for (GTK_WINDOW (chooser), GTK_WINDOW (parent));
+	gtk_window_set_transient_for (GTK_WINDOW (chooser->window), GTK_WINDOW (parent));
 	
-    gtk_window_set_position (GTK_WINDOW (chooser), GTK_WIN_POS_CENTER_ON_PARENT);
-    parole_media_chooser_open_internal (GTK_WIDGET (chooser));
-    
-    gtk_window_set_default_size (GTK_WINDOW (chooser), 680, 480);
+    gtk_window_set_position (GTK_WINDOW (chooser->window), GTK_WIN_POS_CENTER_ON_PARENT);
+
+    gtk_widget_show_all (chooser->window);
 
-    return GTK_WIDGET (chooser);
+    return chooser;
 }
diff --git a/src/parole-mediachooser.h b/src/parole-mediachooser.h
index 46718f0..36e61d4 100644
--- a/src/parole-mediachooser.h
+++ b/src/parole-mediachooser.h
@@ -24,34 +24,20 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
+#include "parole-conf.h"
+
 G_BEGIN_DECLS
 
 #define PAROLE_TYPE_MEDIA_CHOOSER        (parole_media_chooser_get_type () )
 #define PAROLE_MEDIA_CHOOSER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_MEDIA_CHOOSER, ParoleMediaChooser))
 #define PAROLE_IS_MEDIA_CHOOSER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_MEDIA_CHOOSER))
 
-typedef struct ParoleMediaChooserPrivate ParoleMediaChooserPrivate;
-
-typedef struct
-{
-    GtkDialog         		 parent;
-    
-} ParoleMediaChooser;
-
-typedef struct
-{
-    GtkDialogClass 		 parent_class;
-    
-    void			 (*media_files_opened)		    (ParoleMediaChooser *chooser,
-								     gboolean play,
-								     gboolean replace,
-								     GSList *list);
-								     
-} ParoleMediaChooserClass;
+typedef struct ParoleMediaChooser ParoleMediaChooser;
+typedef struct ParoleMediaChooserClass ParoleMediaChooserClass;
 
 GType        			 parole_media_chooser_get_type      (void) G_GNUC_CONST;
 
-GtkWidget			*parole_media_chooser_open_local    (GtkWidget *parent);
+ParoleMediaChooser		*parole_media_chooser_open_local    (GtkWidget *parent);
 								     
 G_END_DECLS
 
diff --git a/src/parole-medialist.c b/src/parole-medialist.c
index 9ff5304..e9b70ed 100644
--- a/src/parole-medialist.c
+++ b/src/parole-medialist.c
@@ -26,18 +26,15 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <unistd.h>
+
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
 #include <glib.h>
 #include <glib/gstdio.h>
 #include <gio/gio.h>
 
-
-#ifdef XFCE_DISABLE_DEPRECATED
-#undef XFCE_DISABLE_DEPRECATED
-#endif
 #include <libxfce4util/libxfce4util.h>
-#include <libxfcegui4/libxfcegui4.h>
 
 #include <parole/parole-file.h>
 
@@ -48,6 +45,7 @@
 #include "parole-medialist.h"
 #include "parole-mediachooser.h"
 #include "parole-open-location.h"
+#include "parole-conf.h"
 
 #include "parole-filters.h"
 #include "parole-pl-parser.h"
@@ -146,6 +144,14 @@ void		parole_media_list_close_save_dialog_cb (GtkButton *button,
 						    
 void		parole_media_list_save_playlist_cb     (GtkButton *button,
 						        ParolePlaylistSave *data);
+
+gboolean	parole_media_list_query_tooltip		(GtkWidget *widget,
+							 gint x,
+							 gint y,
+							 gboolean keyboard_mode,
+							 GtkTooltip *tooltip,
+							 ParoleMediaList *list);
+							 
 /*
  * End of GtkBuilder callbacks
  */
@@ -156,6 +162,7 @@ void		parole_media_list_save_playlist_cb     (GtkButton *button,
 struct ParoleMediaListPrivate
 {
     DBusGConnection     *bus;
+    ParoleConf          *conf;
     GtkWidget 	  	*view;
     GtkWidget		*box;
     GtkListStore	*store;
@@ -188,6 +195,17 @@ parole_media_list_set_widget_sensitive (ParoleMediaList *list, gboolean sensitiv
     gtk_widget_set_sensitive (GTK_WIDGET (list->priv->save), sensitive);
 }
 
+/**
+ * parole_media_list_add:
+ * @ParoleMediaList: a #ParoleMediaList
+ * @file: a #ParoleFile
+ * @emit: TRUE to emit a play signal.
+ * @select_row: TRUE to select the added row
+ * 
+ * All the media items added to the media list view are added by
+ * this function, setting emit to TRUE will cause the player to
+ * start playing the added file.
+ **/
 static void
 parole_media_list_add (ParoleMediaList *list, ParoleFile *file, gboolean emit, gboolean select_row)
 {
@@ -205,16 +223,19 @@ parole_media_list_add (ParoleMediaList *list, ParoleFile *file, gboolean emit, g
 			&iter, 
 			NAME_COL, parole_file_get_display_name (file),
 			DATA_COL, file,
+			LENGTH_COL, parole_taglibc_get_media_length (file),
+			PIXBUF_COL, NULL,
 			-1);
     
-    if ( emit )
+    if ( emit || select_row )
     {
 	path = gtk_tree_model_get_path (GTK_TREE_MODEL (list_store), &iter);
 	row = gtk_tree_row_reference_new (GTK_TREE_MODEL (list_store), path);
 	if ( select_row )
 	    parole_media_list_select_path (list, path);
 	gtk_tree_path_free (path);
-	g_signal_emit (G_OBJECT (list), signals [MEDIA_ACTIVATED], 0, row);
+	if ( emit )
+	    g_signal_emit (G_OBJECT (list), signals [MEDIA_ACTIVATED], 0, row);
 	gtk_tree_row_reference_free (row);
     }
   
@@ -238,14 +259,25 @@ parole_media_list_add (ParoleMediaList *list, ParoleFile *file, gboolean emit, g
 	
 }
 
+/**
+ * parole_media_list_files_open:
+ * @ParoleMediaList: a #ParoleMediaList
+ * @files: a #GSList contains a list of #ParoleFile
+ * @emit: TRUE to emit a play signal.
+ * 
+ **/
 static void
-parole_media_list_files_open (ParoleMediaList *list, GSList *files, 
-			      gboolean replace, gboolean emit)
+parole_media_list_files_open (ParoleMediaList *list, GSList *files, gboolean emit)
 {
     ParoleFile *file;
+    gboolean replace;
     guint len;
     guint i;
     
+    g_object_get (G_OBJECT (list->priv->conf),
+		  "replace-playlist", &replace,
+		  NULL);
+    
     len = g_slist_length (files);
     TRACE ("Adding files");
     
@@ -266,12 +298,16 @@ parole_media_list_files_open (ParoleMediaList *list, GSList *files,
 
 static void
 parole_media_list_files_opened_cb (ParoleMediaChooser *chooser, 
-				   gboolean play,
-				   gboolean replace,
 				   GSList *files, 
 				   ParoleMediaList *list)
 {
-    parole_media_list_files_open (list, files, replace, play);
+    gboolean play;
+    
+    g_object_get (G_OBJECT (list->priv->conf),
+		  "play-opened-files", &play,
+		  NULL);
+    
+    parole_media_list_files_open (list, files, play);
 }
 
 static void
@@ -293,29 +329,37 @@ parole_media_list_location_opened_cb (ParoleOpenLocation *obj, const gchar *loca
 static void
 parole_media_list_open_internal (ParoleMediaList *list)
 {
-    GtkWidget *chooser;
+    ParoleMediaChooser *chooser;
+    
+    TRACE ("start");
     
     chooser = parole_media_chooser_open_local (gtk_widget_get_toplevel (GTK_WIDGET (list)));
 					       
     g_signal_connect (G_OBJECT (chooser), "media_files_opened",
 		      G_CALLBACK (parole_media_list_files_opened_cb), list);
-    
-    gtk_widget_show_all (GTK_WIDGET (chooser));
 }
 
 static void
 parole_media_list_open_location_internal (ParoleMediaList *list)
 {
-    GtkWidget *location;
+    ParoleOpenLocation *location;
     
     location = parole_open_location (gtk_widget_get_toplevel (GTK_WIDGET (list)));
 					       
     g_signal_connect (G_OBJECT (location), "location-opened",
-		          G_CALLBACK (parole_media_list_location_opened_cb), list);
-    
-    gtk_widget_show_all (GTK_WIDGET (location));
+		      G_CALLBACK (parole_media_list_location_opened_cb), list);
 }
 
+/**
+ * parole_media_list_get_files:
+ * @list: a #ParoleMediaList
+ * 
+ * Get a #GSList of all #ParoleFile media files currently displayed in the
+ * media list view
+ * 
+ * Returns: a #GSList contains a list of #ParoleFile
+ * 
+ **/
 static GSList *
 parole_media_list_get_files (ParoleMediaList *list)
 {
@@ -351,15 +395,20 @@ void	parole_media_list_drag_data_received_cb (GtkWidget *widget,
     gchar *path;
     guint i;
     guint added = 0;
+    gboolean play;
     
     parole_window_busy_cursor (GTK_WIDGET (list)->window);
     
+    g_object_get (G_OBJECT (list->priv->conf),
+		  "play-opened-files", &play,
+		  NULL);
+    
     uri_list = g_uri_list_extract_uris ((const gchar *)data->data);
     
     for ( i = 0; uri_list[i] != NULL; i++)
     {
 	path = g_filename_from_uri (uri_list[i], NULL, NULL);
-	added += parole_media_list_add_by_path (list, path, i == 0 ? TRUE : FALSE);
+	added += parole_media_list_add_by_path (list, path, i == 0 ? play : FALSE);
 
 	g_free (path);
     }
@@ -392,6 +441,16 @@ void parole_media_list_close_save_dialog_cb (GtkButton *button, ParolePlaylistSa
     g_free (data);
 }
 
+/**
+ * parole_media_list_get_first_selected_row:
+ * @list: a #ParoleMediaList
+ * 
+ * Gets the first selected row in the media list view.
+ * 
+ * Returns: a #GtkTreeRowReference for the selected row, or NULL if no one is 
+ * 	    currently selected.
+ * 
+ **/
 static GtkTreeRowReference *
 parole_media_list_get_first_selected_row (ParoleMediaList *list)
 {
@@ -438,7 +497,12 @@ void parole_media_list_save_playlist_cb (GtkButton *button, ParolePlaylistSave *
     
     if ( g_access (dirname, W_OK) == -1 )
     {
-	xfce_err ("%s %s %s", _("Error saving playlist file"), dirname, _("Permission denied"));
+	gchar *msg;
+	msg = g_strdup_printf ("%s %s", dirname, _("Permission denied"));
+	parole_dialog_error (GTK_WINDOW (gtk_widget_get_toplevel (data->list->priv->view)),
+			     _("Error saving playlist file"),
+			     msg);
+	g_free (msg);
 	goto out;
     }
     
@@ -447,7 +511,9 @@ void parole_media_list_save_playlist_cb (GtkButton *button, ParolePlaylistSave *
 	format = parole_pl_parser_guess_format_from_extension (filename);
 	if ( format == PAROLE_PL_FORMAT_UNKNOWN )
 	{
-	    xfce_info ("%s", _("Unknown playlist format, Please select a support playlist format"));
+	    parole_dialog_info (GTK_WINDOW (gtk_widget_get_toplevel (data->list->priv->view)),
+				_("Unknown playlist format"),
+				_("Please chooser a supported playlist format"));
 	    goto out;
 	}
     }
@@ -463,6 +529,64 @@ out:
     g_free (dirname);
 }
 
+
+gboolean	parole_media_list_query_tooltip		(GtkWidget *widget,
+							 gint x,
+							 gint y,
+							 gboolean keyboard_mode,
+							 GtkTooltip *tooltip,
+							 ParoleMediaList *list)
+
+{
+    GtkTreePath *path;
+    
+    if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (list->priv->view),
+				       x,
+				       y,
+				       &path,
+				       NULL,
+				       NULL,
+				       NULL))
+    {
+	GtkTreeIter iter;
+	
+	if ( path && gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->store), &iter, path))
+        {
+	    ParoleFile *file;
+	    gchar *tip;
+	    gchar *name;
+	    gchar *len;
+	    
+	    gtk_tree_model_get (GTK_TREE_MODEL (list->priv->store), &iter,
+				DATA_COL, &file,
+				NAME_COL, &name,
+				LENGTH_COL, &len,
+				-1);
+	    
+	    if (!len)
+	    {
+		len = g_strdup (_("Unknown"));
+	    }
+	    
+	    tip = g_strdup_printf ("File: %s\nName: %s\nLength: %s", 
+				   parole_file_get_file_name (file),
+				   name,
+				   len);
+	    
+	    gtk_tooltip_set_text (tooltip, tip);
+	    g_free (tip);
+	    g_free (name);
+	    g_free (len);
+	    gtk_tree_path_free (path);
+	
+	    return TRUE;
+	}
+    }
+				   
+				   
+    return FALSE;
+}
+
 void parole_media_list_format_cursor_changed_cb (GtkTreeView *view, ParolePlaylistSave *data)
 {
     GtkTreeIter iter;
@@ -562,8 +686,42 @@ void parole_media_list_save_cb (GtkButton *button, ParoleMediaList *list)
     g_object_unref (builder);
 }
 
+/**
+ * parole_media_list_get_first_path:
+ * @model: a #GtkTreeModel
+ * 
+ * Get the first path in the model, or NULL if the model is empty
+ * 
+ * Returns: a #GtkTreePath
+ **/
+static GtkTreePath *
+parole_media_list_get_first_path (GtkTreeModel *model) 
+{
+    GtkTreePath *path = NULL;
+    GtkTreeIter iter;
+    
+    if (gtk_tree_model_get_iter_first (model, &iter) )
+    {
+	path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
+    }
+    
+    return path;
+}
+
+/**
+ * 
+ * parole_media_list_paths_to_row_list:
+ * @path_list: a #GList contains a list of #GtkTreePath
+ * @GtkTreeModel: a #GtkTreeModel that contains the paths
+ * 
+ * Converts a list of #GtkTreePath to a list of #GtkTreeRowReference
+ * 
+ * Returns: a #GList contains a list of #GtkTreeRowReference.
+ * 
+ * 
+ **/
 static GList *
-parole_media_list_path_to_row_list (GList *path_list, GtkTreeModel *model)
+parole_media_list_paths_to_row_list (GList *path_list, GtkTreeModel *model)
 {
     GList *row_list = NULL;
     guint len, i;
@@ -585,6 +743,11 @@ parole_media_list_path_to_row_list (GList *path_list, GtkTreeModel *model)
     return row_list;
 }
 
+/**
+ * parole_media_list_remove_clicked_cb:
+ * 
+ * 
+ **/
 void
 parole_media_list_remove_clicked_cb (GtkButton *button, ParoleMediaList *list)
 {
@@ -592,12 +755,40 @@ parole_media_list_remove_clicked_cb (GtkButton *button, ParoleMediaList *list)
     GList *path_list = NULL;
     GList *row_list = NULL;
     GtkTreeIter iter;
+    gboolean row_selected = FALSE;
     gint nch;
     guint len, i;
-    
+
+    /* Get the GtkTreePath GList of all selected rows */
     path_list = gtk_tree_selection_get_selected_rows (list->priv->sel, &model);
 	
-    row_list = parole_media_list_path_to_row_list (path_list, model);
+    /**
+     * Convert them to row references so when we remove one the others always points
+     * to the correct node.
+     **/
+    row_list = parole_media_list_paths_to_row_list (path_list, model);
+
+    /**
+     * Select first path before the first path
+     * that we going to remove.
+     **/
+    if (g_list_length (path_list) != 0)
+    {
+	GtkTreePath *path, *prev;
+	
+	/* Get first item */
+	path = g_list_nth_data (path_list, 0);
+	
+	/* copy it as we don't mess with the list*/
+	prev = gtk_tree_path_copy (path);
+	
+	if ( gtk_tree_path_prev (prev) )
+	{
+	    parole_media_list_select_path (list, prev);
+	    row_selected = TRUE;
+	}
+	gtk_tree_path_free (prev);
+    }
     
     g_list_foreach (path_list, (GFunc) gtk_tree_path_free, NULL);
     g_list_free (path_list);
@@ -621,6 +812,15 @@ parole_media_list_remove_clicked_cb (GtkButton *button, ParoleMediaList *list)
     g_list_foreach (row_list, (GFunc) gtk_tree_row_reference_free, NULL);
     g_list_free (row_list);
     
+    /* No row was selected, then select the first one*/
+    if (!row_selected)
+    {
+	GtkTreePath *path;
+	path = parole_media_list_get_first_path (model);
+	parole_media_list_select_path (list, path);
+	gtk_tree_path_free (path);
+    }
+    
     /*
      * Returns the number of children that iter has. 
      * As a special case, if iter is NULL, 
@@ -644,6 +844,16 @@ parole_media_list_remove_clicked_cb (GtkButton *button, ParoleMediaList *list)
     }
 }
 
+/**
+ * parole_media_list_move_on_down:
+ * 
+ * @store: a #GtkListStore
+ * @iter: a #GtkTreeIter
+ * 
+ * Move the node pointed to by @iter one step down, if the node is the last
+ * one then move it to the first position in the @store.
+ * 
+ **/
 static void
 parole_media_list_move_one_down (GtkListStore *store, GtkTreeIter *iter)
 {
@@ -669,6 +879,15 @@ parole_media_list_move_one_down (GtkListStore *store, GtkTreeIter *iter)
     gtk_tree_iter_free (pos_iter);
 }
 
+/**
+ * parole_media_list_move_many_down:
+ * @path_list: a #GList contains list of #GtkTreePath
+ * @model: a #GtkTreeModel
+ * 
+ * Moves down many nodes pointed to by the paths that are in
+ * the list.
+ * 
+ **/
 static void
 parole_media_list_move_many_down (GList *path_list, GtkTreeModel *model)
 {
@@ -677,7 +896,7 @@ parole_media_list_move_many_down (GList *path_list, GtkTreeModel *model)
     guint len;
     guint i;
     
-    row_list = parole_media_list_path_to_row_list (path_list, model);
+    row_list = parole_media_list_paths_to_row_list (path_list, model);
     
     len = g_list_length (row_list);
     
@@ -700,6 +919,11 @@ parole_media_list_move_many_down (GList *path_list, GtkTreeModel *model)
     g_list_free (row_list);
 }
 
+/**
+ * parole_media_list_media_down_clicked_cb:
+ * 
+ * 
+ **/
 void
 parole_media_list_media_down_clicked_cb (GtkButton *button, ParoleMediaList *list)
 {
@@ -728,6 +952,17 @@ parole_media_list_media_down_clicked_cb (GtkButton *button, ParoleMediaList *lis
     g_list_free (path_list);
 }
 
+
+/**
+ * parole_media_list_move_on_up:
+ * 
+ * @store: a #GtkListStore
+ * @iter: a #GtkTreeIter
+ * 
+ * Move the node pointed to by @iter one step up, if the node is the first
+ * one then move it to the last position in the @store.
+ * 
+ **/
 static void
 parole_media_list_move_one_up (GtkListStore *store, GtkTreeIter *iter)
 {
@@ -756,6 +991,15 @@ parole_media_list_move_one_up (GtkListStore *store, GtkTreeIter *iter)
     gtk_tree_iter_free (pos_iter);
 }
 
+/**
+ * parole_media_list_move_many_up:
+ * @path_list: a #GList contains list of #GtkTreePath
+ * @model: a #GtkTreeModel
+ * 
+ * Moves up many nodes pointed to by the paths that are in
+ * the list.
+ * 
+ **/
 static void
 parole_media_list_move_many_up (GList *path_list, GtkTreeModel *model)
 {
@@ -764,7 +1008,7 @@ parole_media_list_move_many_up (GList *path_list, GtkTreeModel *model)
     guint len;
     guint i;
     
-    row_list = parole_media_list_path_to_row_list (path_list, model);
+    row_list = parole_media_list_paths_to_row_list (path_list, model);
     
     len = g_list_length (row_list);
     
@@ -787,6 +1031,11 @@ parole_media_list_move_many_up (GList *path_list, GtkTreeModel *model)
     g_list_free (row_list);
 }
 
+/**
+ * parole_media_list_media_up_clicked_cb:
+ * 
+ * 
+ **/
 void
 parole_media_list_media_up_clicked_cb (GtkButton *button, ParoleMediaList *list)
 {
@@ -815,6 +1064,11 @@ parole_media_list_media_up_clicked_cb (GtkButton *button, ParoleMediaList *list)
     g_list_free (path_list);
 }
 
+/**
+ * parole_media_list_row_activated_cb:
+ * 
+ * 
+ **/
 void
 parole_media_list_row_activated_cb (GtkTreeView *view, GtkTreePath *path, 
 				    GtkTreeViewColumn *col, ParoleMediaList *list)
@@ -838,6 +1092,90 @@ parole_media_list_selection_changed_cb (GtkTreeSelection *sel, ParoleMediaList *
 }
 
 static void
+parole_media_list_open_folder (GtkWidget *menu)
+{
+    gchar *dirname;
+    
+    dirname = (gchar *) g_object_get_data (G_OBJECT (menu), "folder");
+    
+    if (dirname)
+    {
+	gchar *uri;
+	uri = g_filename_to_uri (dirname, NULL, NULL);
+	TRACE ("Opening %s", dirname);
+	gtk_show_uri (gtk_widget_get_screen (menu),  uri, GDK_CURRENT_TIME, NULL);
+	
+	g_free (uri);
+    }
+}
+
+static void
+parole_media_list_add_open_containing_folder (ParoleMediaList *list, GtkWidget *menu,
+					      gint x, gint y)
+{
+    
+    GtkTreePath *path;
+    
+    
+    if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (list->priv->view),
+                                       x,
+                                       y,
+                                       &path,
+                                       NULL,
+                                       NULL,
+                                       NULL))
+    {
+	
+	GtkTreeIter iter;
+	
+	if ( path && gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->store), &iter, path))
+        {
+	    ParoleFile *file;
+	    const gchar *filename;
+	    const gchar *uri;
+	    
+	    gtk_tree_model_get (GTK_TREE_MODEL (list->priv->store), &iter,
+				DATA_COL, &file,
+				-1);
+			    
+	    filename = parole_file_get_file_name (file);
+	    uri = parole_file_get_uri (file);
+	    
+	    if (g_str_has_prefix (uri, "file:///"))
+	    {
+		GtkWidget *mi, *img;
+		gchar *dirname;
+	    
+		dirname = g_path_get_dirname (filename);
+		
+		/* Clear */
+		mi = gtk_image_menu_item_new_with_label (_("Open Containing Folder"));
+		img = gtk_image_new_from_stock (GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU);
+		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img);
+		gtk_widget_set_sensitive (mi, TRUE);
+		gtk_widget_show (mi);
+		g_signal_connect_swapped (mi, "activate",
+					  G_CALLBACK (parole_media_list_open_folder), menu);
+		
+		g_object_set_data (G_OBJECT (menu), "folder", dirname);
+		
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+		
+		
+		mi = gtk_separator_menu_item_new ();
+		gtk_widget_show (mi);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+		
+		
+	    }
+	    
+	    gtk_tree_path_free (path);
+	}
+    }
+}
+
+
+static void
 parole_media_list_clear_list (ParoleMediaList *list)
 {
     gtk_list_store_clear (GTK_LIST_STORE (list->priv->store));
@@ -845,6 +1183,24 @@ parole_media_list_clear_list (ParoleMediaList *list)
 }
 
 static void
+replace_list_activated_cb (GtkWidget *mi, ParoleConf *conf)
+{
+    g_object_set (G_OBJECT (conf),
+		  "replace-playlist", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mi)),
+		  NULL);
+		
+}
+
+static void
+play_opened_files_activated_cb (GtkWidget *mi, ParoleConf *conf)
+{
+    g_object_set (G_OBJECT (conf),
+		  "play-opened-files", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (mi)),
+		  NULL);
+		
+}
+
+static void
 save_list_activated_cb (GtkWidget *mi)
 {
     gboolean active;
@@ -855,12 +1211,123 @@ save_list_activated_cb (GtkWidget *mi)
 }
 
 static void
-parole_media_list_show_menu (ParoleMediaList *list, guint button, guint activate_time)
+repeat_activated_cb (GtkWidget *mi, ParoleConf *conf)
+{
+    g_object_set (G_OBJECT (conf),
+		  "repeat", gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (mi)),
+		  NULL);
+}
+
+static void
+shuffle_activated_cb (GtkWidget *mi, ParoleConf *conf)
+{
+    g_object_set (G_OBJECT (conf),
+		  "shuffle", gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (mi)),
+		  NULL);
+}
+
+static void
+parole_media_list_destroy_menu (GtkWidget *menu)
+{
+    gchar *dirname;
+    
+    dirname = (gchar *) g_object_get_data (G_OBJECT (menu), "folder");
+    
+    if (dirname)
+    {
+	g_free (dirname);
+    }
+    
+    gtk_widget_destroy (menu);
+}
+
+static void
+parole_media_list_show_menu (ParoleMediaList *list, GdkEventButton *ev)
 {
     GtkWidget *menu, *mi;
+    gboolean val;
+    guint button = ev->button; 
+    guint activate_time = ev->time;
 
     menu = gtk_menu_new ();
+
+    parole_media_list_add_open_containing_folder (list, menu, (gint)ev->x, (gint)ev->y);
     
+
+    /**
+     * Repeat playing.
+     **/
+    g_object_get (G_OBJECT (list->priv->conf),
+		  "repeat", &val,
+		  NULL);
+
+    mi = gtk_check_menu_item_new_with_label (_("Repeat"));
+    gtk_widget_set_sensitive (mi, TRUE);
+    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), val);
+    g_signal_connect (mi, "activate",
+                      G_CALLBACK (repeat_activated_cb), list->priv->conf);
+			      
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+    gtk_widget_show (mi);
+
+    /**
+     * Shuffle playing.
+     **/
+    g_object_get (G_OBJECT (list->priv->conf),
+		  "shuffle", &val,
+		  NULL);
+
+    mi = gtk_check_menu_item_new_with_label (_("Shuffle"));
+    gtk_widget_set_sensitive (mi, TRUE);
+    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), val);
+    g_signal_connect (mi, "activate",
+                      G_CALLBACK (shuffle_activated_cb), list->priv->conf);
+			      
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+    gtk_widget_show (mi);
+
+    /**
+     * Separator
+     **/
+    mi = gtk_separator_menu_item_new ();
+    gtk_widget_show (mi);
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+
+    /**
+     * replace playlist
+     **/
+    g_object_get (G_OBJECT (list->priv->conf),
+		  "replace-playlist", &val,
+		  NULL);
+
+    mi = gtk_check_menu_item_new_with_label (_("Replace playlist when opening files"));
+    gtk_widget_set_sensitive (mi, TRUE);
+    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), val);
+    g_signal_connect (mi, "activate",
+                      G_CALLBACK (replace_list_activated_cb), list->priv->conf);
+			      
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+    gtk_widget_show (mi);
+    
+    /**
+     * Play when files are open.
+     **/
+    
+    g_object_get (G_OBJECT (list->priv->conf),
+		  "play-opened-files", &val,
+		  NULL);
+    mi = gtk_check_menu_item_new_with_label (_("Play opened files"));
+    gtk_widget_set_sensitive (mi, TRUE);
+    gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), val);
+    g_signal_connect (mi, "activate",
+                      G_CALLBACK (play_opened_files_activated_cb), list->priv->conf);
+			      
+    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+    gtk_widget_show (mi);
+    
+    /**
+     * Remember media list entries
+     **/
     mi = gtk_check_menu_item_new_with_label (_("Remember playlist"));
     gtk_widget_set_sensitive (mi, TRUE);
     gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi),
@@ -874,6 +1341,9 @@ parole_media_list_show_menu (ParoleMediaList *list, guint button, guint activate
     
     gtk_widget_show (mi);
     
+    /**
+     * Separator
+     **/
     mi = gtk_separator_menu_item_new ();
     gtk_widget_show (mi);
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
@@ -889,7 +1359,7 @@ parole_media_list_show_menu (ParoleMediaList *list, guint button, guint activate
     gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
     
     g_signal_connect_swapped (menu, "selection-done",
-                              G_CALLBACK (gtk_widget_destroy), menu);
+                              G_CALLBACK (parole_media_list_destroy_menu), menu);
     
     gtk_menu_popup (GTK_MENU (menu), 
                     NULL, NULL,
@@ -902,7 +1372,7 @@ parole_media_list_button_release_event (GtkWidget *widget, GdkEventButton *ev, P
 {
     if ( ev->button == 3 )
     {
-	parole_media_list_show_menu (list, ev->button, ev->time);
+	parole_media_list_show_menu (list, ev);
 	return TRUE;
     }
     
@@ -992,7 +1462,7 @@ parole_media_list_setup_view (ParoleMediaList *list)
     GtkTreeViewColumn *col;
     GtkCellRenderer *renderer;
 
-    list_store = gtk_list_store_new (COL_NUMBERS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_OBJECT);
+    list_store = gtk_list_store_new (COL_NUMBERS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_OBJECT);
 
     gtk_tree_view_set_model (GTK_TREE_VIEW (list->priv->view), GTK_TREE_MODEL(list_store));
     
@@ -1004,6 +1474,11 @@ parole_media_list_setup_view (ParoleMediaList *list)
     gtk_tree_view_column_pack_start(col, renderer, FALSE);
     gtk_tree_view_column_set_attributes(col, renderer, "pixbuf", PIXBUF_COL, NULL);
 
+
+    /**
+     * Name col
+     * 
+     **/
     renderer = gtk_cell_renderer_text_new();
     
     gtk_tree_view_column_pack_start (col, renderer, TRUE);
@@ -1012,6 +1487,17 @@ parole_media_list_setup_view (ParoleMediaList *list)
 		  "ellipsize", PANGO_ELLIPSIZE_END, 
 		  NULL);
     
+    
+    /**
+     * Media length
+     * 
+     **/
+    renderer = gtk_cell_renderer_text_new();
+    
+    gtk_tree_view_column_pack_start (col, renderer, FALSE);
+    gtk_tree_view_column_set_attributes (col, renderer, "text", LENGTH_COL, NULL);
+    
+    
     gtk_tree_view_append_column (GTK_TREE_VIEW (list->priv->view), col);
     gtk_tree_view_column_set_title (col, _("Media list"));
 
@@ -1037,6 +1523,8 @@ parole_media_list_init (ParoleMediaList *list)
     
     list->priv->bus = parole_g_session_bus_get ();
     
+    list->priv->conf = parole_conf_new ();
+    
     builder = parole_builder_new_from_string (playlist_ui, playlist_ui_length);
     
     list->priv->view = GTK_WIDGET (gtk_builder_get_object (builder, "media-list"));
@@ -1082,8 +1570,13 @@ parole_media_list_get (void)
 void parole_media_list_load (ParoleMediaList *list)
 {
     gboolean    load_saved_list;
+    gboolean    play;
     GSList     *fileslist = NULL;
     
+    g_object_get (G_OBJECT (list->priv->conf),
+		  "play-opened-files", &play,
+		  NULL);
+    
     load_saved_list = parole_rc_read_entry_bool ("SAVE_LIST_ON_EXIT", PAROLE_RC_GROUP_GENERAL, FALSE);
     
     if ( load_saved_list )
@@ -1098,7 +1591,7 @@ void parole_media_list_load (ParoleMediaList *list)
 	    fileslist = parole_pl_parser_parse_from_file_by_extension (playlist_file);
 	    g_free (playlist_file);
 	    
-	    parole_media_list_files_opened_cb (NULL, FALSE, FALSE, fileslist, list);
+	    parole_media_list_files_open (list, fileslist, play);
 	    g_slist_free (fileslist);
 	}
     }
@@ -1120,7 +1613,7 @@ parole_media_list_add_by_path (ParoleMediaList *list, const gchar *path, gboolea
     
     parole_get_media_files (filter, path, TRUE, &files_list);
     
-    parole_media_list_files_open (list, files_list, FALSE, emit);
+    parole_media_list_files_open (list, files_list, emit);
     
     len = g_slist_length (files_list);
     ret = len == 0 ? FALSE : TRUE;
@@ -1150,7 +1643,7 @@ GtkTreeRowReference *parole_media_list_get_next_row (ParoleMediaList *list,
     if ( gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->store), &iter, path))
     {
 	next = gtk_tree_row_reference_new (GTK_TREE_MODEL (list->priv->store), path);
-	parole_media_list_select_path (list, path);
+	//parole_media_list_select_path (list, path);
     }
     else if ( repeat ) /* Repeat playing ?*/
     {
@@ -1184,7 +1677,7 @@ GtkTreeRowReference *parole_media_list_get_prev_row (ParoleMediaList *list,
     if ( gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->store), &iter, path))
     {
 	prev = gtk_tree_row_reference_new (GTK_TREE_MODEL (list->priv->store), path);
-	parole_media_list_select_path (list, path);
+	//parole_media_list_select_path (list, path);
     }
     else
 	prev = row;
@@ -1217,7 +1710,7 @@ GtkTreeRowReference *parole_media_list_get_row_random (ParoleMediaList *list)
     if ( gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->store), &iter, path))
     {
 	row  = gtk_tree_row_reference_new (GTK_TREE_MODEL (list->priv->store), path);
-	parole_media_list_select_path (list, path);
+	//parole_media_list_select_path (list, path);
     }
     
     gtk_tree_path_free (path);
@@ -1237,6 +1730,13 @@ gboolean parole_media_list_is_empty (ParoleMediaList *list)
     return !gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list->priv->store), &iter);
 }
 
+/**
+ * parole_media_list_get_first_row:
+ * @list: a #ParoleMediaList
+ * 
+ * 
+ * Returns: a #GtkTreeRowReference of the first row in the media list.
+ **/
 GtkTreeRowReference *parole_media_list_get_first_row (ParoleMediaList *list)
 {
     GtkTreeRowReference *row = NULL;
@@ -1250,11 +1750,30 @@ GtkTreeRowReference *parole_media_list_get_first_row (ParoleMediaList *list)
     return row;
 }
 
+/**
+ * parole_media_list_get_selected_row:
+ * @list: a #ParoleMediaList
+ * 
+ * 
+ * Returns: a #GtkTreeRowReference of the selected row.
+ **/
 GtkTreeRowReference *parole_media_list_get_selected_row (ParoleMediaList *list)
 {
     return parole_media_list_get_first_selected_row (list);
 }
 
+void parole_media_list_select_row (ParoleMediaList *list, GtkTreeRowReference *row)
+{
+    GtkTreePath *path;
+    
+    if ( gtk_tree_row_reference_valid (row) )
+    {
+	path = gtk_tree_row_reference_get_path (row);
+	parole_media_list_select_path (list, path);
+	gtk_tree_path_free (path);
+    }
+}
+
 void parole_media_list_set_row_pixbuf  (ParoleMediaList *list, GtkTreeRowReference *row, GdkPixbuf *pix)
 {
     GtkTreeIter iter;
@@ -1289,6 +1808,23 @@ void parole_media_list_set_row_name (ParoleMediaList *list, GtkTreeRowReference
     }
 }
 
+void parole_media_list_set_row_length (ParoleMediaList *list, GtkTreeRowReference *row, const gchar *len)
+{
+    GtkTreeIter iter;
+    GtkTreePath *path;
+    
+    if ( gtk_tree_row_reference_valid (row) )
+    {
+	path = gtk_tree_row_reference_get_path (row);
+	
+	if ( gtk_tree_model_get_iter (GTK_TREE_MODEL (list->priv->store), &iter, path) )
+	{
+	    gtk_list_store_set (list->priv->store, &iter, LENGTH_COL, len, -1);
+	}
+	gtk_tree_path_free (path);
+    }
+}
+
 void parole_media_list_open (ParoleMediaList *list)
 {
     parole_media_list_open_internal (list);
@@ -1306,9 +1842,9 @@ gboolean parole_media_list_add_files (ParoleMediaList *list, gchar **filenames)
     
     for ( i = 0; filenames && filenames[i] != NULL; i++)
     {
-	/**
-	 * File on disk
-	 **/
+	/*
+	 * File on disk?
+	 */
 	if ( g_file_test (filenames[i], G_FILE_TEST_EXISTS ) )
 	{
 	    added += parole_media_list_add_by_path (list, filenames[i], i == 0 ? TRUE : FALSE);
@@ -1323,7 +1859,7 @@ gboolean parole_media_list_add_files (ParoleMediaList *list, gchar **filenames)
 	}
     }
     
-    return added == i;
+    return added > 0;
 }
 
 void parole_media_list_save_list (ParoleMediaList *list)
diff --git a/src/parole-medialist.h b/src/parole-medialist.h
index 821dd11..a548f43 100644
--- a/src/parole-medialist.h
+++ b/src/parole-medialist.h
@@ -33,6 +33,7 @@ enum
 {
     PIXBUF_COL,
     NAME_COL,
+    LENGTH_COL,
     DATA_COL,
     COL_NUMBERS
 };
@@ -81,6 +82,9 @@ GtkTreeRowReference             *parole_media_list_get_first_row    (ParoleMedia
 
 GtkTreeRowReference		*parole_media_list_get_selected_row (ParoleMediaList *list);
 
+void				 parole_media_list_select_row 	    (ParoleMediaList *list,
+								     GtkTreeRowReference *row);
+
 GtkTreeRowReference             *parole_media_list_get_next_row     (ParoleMediaList *list,
 								     GtkTreeRowReference *row,
 								     gboolean repeat);
@@ -93,11 +97,16 @@ GtkTreeRowReference		*parole_media_list_get_row_random   (ParoleMediaList *list)
 void				 parole_media_list_set_row_pixbuf   (ParoleMediaList *list,
 								     GtkTreeRowReference *row,
 								     GdkPixbuf *pix);
-								     
+
 void				 parole_media_list_set_row_name     (ParoleMediaList *list,
 							             GtkTreeRowReference *row,
 								     const gchar *name);
 
+
+void				 parole_media_list_set_row_length   (ParoleMediaList *list,
+							             GtkTreeRowReference *row,
+								     const gchar *length);
+
 void				 parole_media_list_open		    (ParoleMediaList *list);
 
 void			         parole_media_list_open_location    (ParoleMediaList *list);
diff --git a/src/parole-open-location.c b/src/parole-open-location.c
index 4b0d955..0d0af5d 100644
--- a/src/parole-open-location.c
+++ b/src/parole-open-location.c
@@ -30,15 +30,26 @@
 
 #include "parole-open-location.h"
 #include "parole-rc-utils.h"
+#include "parole-builder.h"
+
+#include "interfaces/open-location_ui.h"
 
 static void parole_open_location_finalize   (GObject *object);
 
-#define PAROLE_OPEN_LOCATION_GET_PRIVATE(o) \
-(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_OPEN_LOCATION, ParoleOpenLocationPrivate))
+struct ParoleOpenLocation
+{
+    GObject         	parent;
+    
+    
+    GtkWidget 	       *entry;
+};
 
-struct ParoleOpenLocationPrivate
+struct ParoleOpenLocationClass
 {
-    GtkWidget *entry;
+    GObjectClass 	parent_class;
+    
+    void		(*location_opened)	(ParoleOpenLocation *self,
+						 const gchar *address);
 };
 
 enum
@@ -55,7 +66,7 @@ enum
 
 static guint signals [LAST_SIGNAL] = { 0 };
 
-G_DEFINE_TYPE (ParoleOpenLocation, parole_open_location, GTK_TYPE_DIALOG)
+G_DEFINE_TYPE (ParoleOpenLocation, parole_open_location, G_TYPE_OBJECT)
 
 static void
 parole_open_location_response_cb (GtkDialog *dialog, gint response_id, ParoleOpenLocation *self)
@@ -64,19 +75,19 @@ parole_open_location_response_cb (GtkDialog *dialog, gint response_id, ParoleOpe
 
     if ( response_id == GTK_RESPONSE_OK )
     {
-	location = gtk_entry_get_text (GTK_ENTRY (self->priv->entry));
+	location = gtk_entry_get_text (GTK_ENTRY (self->entry));
 	
 	if ( !location || strlen (location) == 0)
 	    goto out;
 
 	TRACE ("Location %s", location);
 
-	gtk_widget_hide (GTK_WIDGET (self));
+	gtk_widget_hide (GTK_WIDGET (dialog));
 	g_signal_emit (G_OBJECT (self), signals [LOCATION_OPENED], 0, location);
     }
 
     out:
-	gtk_widget_destroy (GTK_WIDGET (self));
+	gtk_widget_destroy (GTK_WIDGET (dialog));
 }
 
 static GtkTreeModel *
@@ -134,14 +145,11 @@ parole_open_location_class_init (ParoleOpenLocationClass *klass)
                       NULL, NULL,
                       g_cclosure_marshal_VOID__STRING,
                       G_TYPE_NONE, 1, G_TYPE_STRING);
-
-    g_type_class_add_private (klass, sizeof (ParoleOpenLocationPrivate));
 }
 
 static void
 parole_open_location_init (ParoleOpenLocation *self)
 {
-    self->priv = PAROLE_OPEN_LOCATION_GET_PRIVATE (self);
 }
 
 static void
@@ -161,37 +169,32 @@ parole_open_location_clear_history (GtkTreeModel *model)
     gtk_list_store_clear (GTK_LIST_STORE (model));
 }
 
-GtkWidget *parole_open_location (GtkWidget *parent)
+ParoleOpenLocation *parole_open_location (GtkWidget *parent)
 {
+    ParoleOpenLocation *self;
+    GtkWidget *dialog;
     GtkEntryCompletion *cmpl;
     GtkTreeModel *model;
-    GtkWidget *label;
-    GtkWidget *clear;
-    GtkWidget *img;
-    GtkWidget *vbox;
-    GtkWidget *hbox;
-    
-    ParoleOpenLocation *self = NULL;
+    GtkBuilder *builder;
     
     self = g_object_new (PAROLE_TYPE_OPEN_LOCATION, NULL);
     
-    if ( parent )
-	gtk_window_set_transient_for (GTK_WINDOW (self), GTK_WINDOW (parent));
+    builder = parole_builder_new_from_string (open_location_ui, open_location_ui_length);
     
-    gtk_window_set_title (GTK_WINDOW (self), _("Open location..."));
-    gtk_window_set_default_size (GTK_WINDOW (self), 360, 40);
-    gtk_window_set_position (GTK_WINDOW (self), GTK_WIN_POS_CENTER_ON_PARENT);
+    dialog = GTK_WIDGET (gtk_builder_get_object (builder, "open-location"));
     
-    label = gtk_label_new (NULL);
-    gtk_label_set_markup (GTK_LABEL (label), _("<b>Open location of media file or live stream:</b>"));
+    if ( parent )
+	gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
+	
+    gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER_ON_PARENT);
     
-    self->priv->entry = gtk_entry_new ();
+    self->entry = GTK_WIDGET (gtk_builder_get_object (builder, "entry"));
     model = parole_open_location_get_completion_model ();
     
-    gtk_entry_set_activates_default (GTK_ENTRY (self->priv->entry), TRUE);
+    gtk_entry_set_activates_default (GTK_ENTRY (self->entry), TRUE);
     cmpl = gtk_entry_completion_new ();
     
-    gtk_entry_set_completion (GTK_ENTRY (self->priv->entry), cmpl);
+    gtk_entry_set_completion (GTK_ENTRY (self->entry), cmpl);
     gtk_entry_completion_set_model (cmpl, model);
     
     gtk_entry_completion_set_text_column (cmpl, 0);
@@ -199,46 +202,20 @@ GtkWidget *parole_open_location (GtkWidget *parent)
 					 (GtkEntryCompletionMatchFunc) parole_open_location_match, 
 					 model, 
 					 NULL);
-	
-    img = gtk_image_new_from_stock (GTK_STOCK_CLEAR, GTK_ICON_SIZE_BUTTON);
-    
-    clear = gtk_button_new_with_label (_("Clear history"));
-    g_signal_connect_swapped (clear, "clicked",
-			      G_CALLBACK (parole_open_location_clear_history), model);
-
-    g_object_set (G_OBJECT (clear),
-		  "image", img,
-		  NULL);
-
-    vbox = gtk_vbox_new (TRUE, 4);
-    hbox = gtk_hbox_new (FALSE, 8);
-    
-    gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
-    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
     
-    gtk_box_pack_start (GTK_BOX (hbox), self->priv->entry, TRUE, TRUE, 0);
-    gtk_box_pack_start (GTK_BOX (hbox), clear, FALSE, FALSE, 0);
+    gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
     
-    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (self)->vbox),
-			vbox,
-			TRUE,   
-			TRUE,
-			0);   
-    
-    gtk_dialog_add_buttons (GTK_DIALOG (self), 
-			    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-			    GTK_STOCK_OPEN, GTK_RESPONSE_OK,
-			    NULL);
-    
-    gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_OK);
+    g_signal_connect_swapped (gtk_builder_get_object (builder, "clear-history"), "clicked",
+			      G_CALLBACK (parole_open_location_clear_history), model);
     
-    g_signal_connect (self, "delete-event",
-		      G_CALLBACK (gtk_widget_destroy), self);
+    g_signal_connect (dialog, "delete-event",
+		      G_CALLBACK (gtk_widget_destroy), NULL);
 		      
-    g_signal_connect (self, "response",
+    g_signal_connect (dialog, "response",
 		      G_CALLBACK (parole_open_location_response_cb), self);
-		      
-    gtk_widget_show_all (GTK_WIDGET (self));
     
-    return GTK_WIDGET (self);
+    gtk_widget_show_all (dialog);
+    g_object_unref (builder);
+    
+    return self;
 }
diff --git a/src/parole-open-location.h b/src/parole-open-location.h
index 15ee1b1..2c25994 100644
--- a/src/parole-open-location.h
+++ b/src/parole-open-location.h
@@ -30,27 +30,12 @@ G_BEGIN_DECLS
 #define PAROLE_OPEN_LOCATION(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_OPEN_LOCATION, ParoleOpenLocation))
 #define PAROLE_IS_OPEN_LOCATION(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_OPEN_LOCATION))
 
-typedef struct ParoleOpenLocationPrivate ParoleOpenLocationPrivate;
-
-typedef struct
-{
-    GtkDialog         		   parent;
-    ParoleOpenLocationPrivate     *priv;
-    
-} ParoleOpenLocation;
-
-typedef struct
-{
-    GtkDialogClass 		   parent_class;
-    
-    void			  (*location_opened)		       (ParoleOpenLocation *self,
-								        const gchar *address);
-    
-} ParoleOpenLocationClass;
+typedef struct ParoleOpenLocation      ParoleOpenLocation;
+typedef struct ParoleOpenLocationClass ParoleOpenLocationClass;
 
 GType        			   parole_open_location_get_type       (void) G_GNUC_CONST;
 
-GtkWidget			  *parole_open_location 	       (GtkWidget *parent);
+ParoleOpenLocation		  *parole_open_location 	       (GtkWidget *parent);
 
 G_END_DECLS
 
diff --git a/src/parole-utils.c b/src/parole-utils.c
index b0cb8c8..96b21ec 100644
--- a/src/parole-utils.c
+++ b/src/parole-utils.c
@@ -38,6 +38,10 @@
 #include <linux/cdrom.h>
 #endif
 
+#ifdef HAVE_TAGLIBC
+#include <taglib/tag_c.h>
+#endif
+
 #include <libxfce4util/libxfce4util.h>
 
 #include <parole/parole.h>
@@ -595,3 +599,73 @@ parole_get_uri_from_unix_device (const gchar *device)
     
     return uri;
 }
+
+/**
+ * parole_format_media_length:
+ * 
+ * @total_seconds: lenght of the media file in seconds
+ * 
+ * Returns : formated string for the media lenght
+ **/
+gchar *parole_format_media_length (gint total_seconds)
+{
+    gchar *timestring;
+    
+    gint  hours;
+    gint  minutes;
+    gint  seconds;
+
+    minutes =  total_seconds / 60;
+    seconds = total_seconds % 60;
+    hours = minutes / 60;
+    minutes = minutes % 60;
+
+    if ( hours == 0 )
+    {
+        timestring = g_strdup_printf ("%02i:%02i", minutes, seconds);
+    }
+    else
+    {
+        timestring = g_strdup_printf ("%i:%02i:%02i", hours, minutes, seconds);
+    }
+    
+    return timestring;
+}
+
+
+/**
+ * parole_taglibc_get_media_length:
+ * 
+ * @ParoleFile: a ParoleFile
+ * 
+ * Returns: the length of the media only if the file is a local
+ *          media file.
+ **/
+gchar *parole_taglibc_get_media_length (ParoleFile *file)
+{
+    #ifdef HAVE_TAGLIBC
+    
+    TagLib_File *tag_file;
+    
+    if (g_str_has_prefix (parole_file_get_uri (file), "file:/"))
+    {
+        tag_file = taglib_file_new (parole_file_get_file_name (file));
+    
+        if ( tag_file )
+        {
+            gint length = 0;
+            const TagLib_AudioProperties *prop = taglib_file_audioproperties (tag_file);
+            
+            if (prop)
+                length = taglib_audioproperties_length (prop);
+            
+            taglib_file_free (tag_file);
+            
+            if (length != 0)
+                return parole_format_media_length (length);
+        }
+    }
+    #endif /* HAVE_TAGLIBC */
+    
+    return NULL;
+}
diff --git a/src/parole-utils.h b/src/parole-utils.h
index d38a2ef..9726015 100644
--- a/src/parole-utils.h
+++ b/src/parole-utils.h
@@ -50,4 +50,8 @@ gchar 	       *parole_guess_uri_from_mount 		(GMount *mount);
 							 
 gchar          *parole_get_uri_from_unix_device		(const gchar *device);
 
+gchar          *parole_format_media_length              (gint total_seconds);
+
+gchar          *parole_taglibc_get_media_length         (ParoleFile *file);
+
 #endif /* __PAROLE_UTILS_ */



More information about the Xfce4-commits mailing list