[Goodies-commits] r7778 - in parole/trunk: . data/interfaces data/mime parole po

Ali Abdallah aliov at xfce.org
Thu Jul 23 23:35:01 CEST 2009


Author: aliov
Date: 2009-07-23 21:35:01 +0000 (Thu, 23 Jul 2009)
New Revision: 7778

Added:
   parole/trunk/data/interfaces/save-playlist.ui
   parole/trunk/parole/parole-about.c
   parole/trunk/parole/parole-about.h
   parole/trunk/parole/parole-builder.c
   parole/trunk/parole/parole-builder.h
   parole/trunk/parole/parole-file.c
   parole/trunk/parole/parole-file.h
   parole/trunk/parole/parole-pl-parser.c
   parole/trunk/parole/parole-pl-parser.h
Removed:
   parole/trunk/common/
   parole/trunk/parole/parole-mediafile.c
   parole/trunk/parole/parole-mediafile.h
   parole/trunk/parole/parole-sidebar.c
   parole/trunk/parole/parole-sidebar.h
Modified:
   parole/trunk/ChangeLog
   parole/trunk/Makefile.am
   parole/trunk/TODO
   parole/trunk/configure.ac.in
   parole/trunk/data/interfaces/Makefile.am
   parole/trunk/data/interfaces/mediachooser.ui
   parole/trunk/data/interfaces/openlocation.ui
   parole/trunk/data/interfaces/parole-settings.ui
   parole/trunk/data/interfaces/parole.ui
   parole/trunk/data/interfaces/playlist.ui
   parole/trunk/data/mime/mime-type-list.txt
   parole/trunk/parole/Makefile.am
   parole/trunk/parole/parole-conf-dialog.c
   parole/trunk/parole/parole-debug.h
   parole/trunk/parole/parole-disc.c
   parole/trunk/parole/parole-filters.c
   parole/trunk/parole/parole-filters.h
   parole/trunk/parole/parole-gst.c
   parole/trunk/parole/parole-mediachooser.c
   parole/trunk/parole/parole-mediachooser.h
   parole/trunk/parole/parole-medialist.c
   parole/trunk/parole/parole-medialist.h
   parole/trunk/parole/parole-player.c
   parole/trunk/parole/parole-plugin.c
   parole/trunk/parole/parole-plugin.h
   parole/trunk/parole/parole-plugins-manager.c
   parole/trunk/parole/parole-statusbar.c
   parole/trunk/parole/parole-stream.c
   parole/trunk/parole/parole-utils.c
   parole/trunk/parole/parole-utils.h
   parole/trunk/po/POTFILES.in
   parole/trunk/po/parole-media-player.pot
Log:
	* parole/parole-gst.c Only emit media progressed signal when the
	state is playing.
	* parole/parole-pl-parser.{c,h} added a playlist parser code based
	on code from totem and from xfmedia.
	* parole/parole-filters.c added filters for playlist files.
	* po/POTFILES.in updates.
	* delete the common dir as it is useless.
	* Change ParoleMediaFile to ParoleFile as it doesn't only describe
	a media file.
	

Modified: parole/trunk/ChangeLog
===================================================================
--- parole/trunk/ChangeLog	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/ChangeLog	2009-07-23 21:35:01 UTC (rev 7778)
@@ -1,3 +1,14 @@
+2009-07-23: 23:00 Ali aliov at xfce.org
+	* parole/parole-gst.c Only emit media progressed signal when the
+	state is playing.
+	* parole/parole-pl-parser.{c,h} added a playlist parser code based
+	on code from totem and from xfmedia.
+	* parole/parole-filters.c added filters for playlist files.
+	* po/POTFILES.in updates.
+	* delete the common dir as it is useless.
+	* Change ParoleMediaFile to ParoleFile as it doesn't only describe
+	a media file.
+	
 2009-07-19: 10:00 Ali aliov at xfce.org
 	* Handled disc uri's like dvd:/ from the command line.
 

Modified: parole/trunk/Makefile.am
===================================================================
--- parole/trunk/Makefile.am	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/Makefile.am	2009-07-23 21:35:01 UTC (rev 7778)
@@ -1,6 +1,5 @@
 SUBDIRS =  		\
 	data		\
-	common		\
 	parole 		\
 	plugins		\
 	docs		\

Modified: parole/trunk/TODO
===================================================================
--- parole/trunk/TODO	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/TODO	2009-07-23 21:35:01 UTC (rev 7778)
@@ -1,7 +1,8 @@
 === Media player ===
 * Complete the shortcut keys.
-* Handle playlist(s), save/load.
+* Better support for cdda.
 * Better statusbar information.
+* Support some playlist title entity.
 * Encoding support for subtitles.
 * Configure plugins dialog to load/unload plugins.
 * ...

Modified: parole/trunk/configure.ac.in
===================================================================
--- parole/trunk/configure.ac.in	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/configure.ac.in	2009-07-23 21:35:01 UTC (rev 7778)
@@ -150,7 +150,6 @@
 data/icons/Makefile
 data/mime/Makefile
 data/desktop/Makefile
-common/Makefile
 parole/Makefile
 plugins/Makefile
 plugins/properties/Makefile

Modified: parole/trunk/data/interfaces/Makefile.am
===================================================================
--- parole/trunk/data/interfaces/Makefile.am	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/data/interfaces/Makefile.am	2009-07-23 21:35:01 UTC (rev 7778)
@@ -3,7 +3,8 @@
 	parole-settings.ui			\
 	playlist.ui				\
 	mediachooser.ui				\
-	openlocation.ui
+	openlocation.ui				\
+	save-playlist.ui
 
 interfaces_h = 					\
 	$(interfaces:.ui=_ui.h)
@@ -25,6 +26,10 @@
 
 openlocation_ui.h: openlocation.ui
 	exo-csource --static --strip-comments --strip-content --name=openlocation_ui $< > $@
+
+save-playlist_ui.h: save-playlist.ui
+	exo-csource --static --strip-comments --strip-content --name=save_playlist_ui $< > $@
+
 endif
 
 DISTCLEANFILES =				\

Modified: parole/trunk/data/interfaces/mediachooser.ui
===================================================================
--- parole/trunk/data/interfaces/mediachooser.ui	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/data/interfaces/mediachooser.ui	2009-07-23 21:35:01 UTC (rev 7778)
@@ -29,7 +29,7 @@
         <property name="layout_style">end</property>
         <child>
           <object class="GtkButton" id="close">
-            <property name="label" translatable="yes">gtk-close</property>
+            <property name="label" translatable="no">gtk-close</property>
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>

Modified: parole/trunk/data/interfaces/openlocation.ui
===================================================================
--- parole/trunk/data/interfaces/openlocation.ui	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/data/interfaces/openlocation.ui	2009-07-23 21:35:01 UTC (rev 7778)
@@ -31,7 +31,7 @@
         <property name="layout_style">end</property>
         <child>
           <object class="GtkButton" id="close">
-            <property name="label" translatable="yes">gtk-close</property>
+            <property name="label" translatable="no">gtk-close</property>
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>
@@ -46,7 +46,7 @@
         </child>
         <child>
           <object class="GtkButton" id="open">
-            <property name="label" translatable="yes">gtk-open</property>
+            <property name="label" translatable="no">gtk-open</property>
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">True</property>

Modified: parole/trunk/data/interfaces/parole-settings.ui
===================================================================
--- parole/trunk/data/interfaces/parole-settings.ui	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/data/interfaces/parole-settings.ui	2009-07-23 21:35:01 UTC (rev 7778)
@@ -234,7 +234,7 @@
             <property name="visible">True</property>
             <child>
               <object class="GtkButton" id="help">
-                <property name="label" translatable="yes">gtk-help</property>
+                <property name="label" translatable="no">gtk-help</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
@@ -248,7 +248,7 @@
             </child>
             <child>
               <object class="GtkButton" id="close">
-                <property name="label" translatable="yes">gtk-close</property>
+                <property name="label" translatable="no">gtk-close</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>

Modified: parole/trunk/data/interfaces/parole.ui
===================================================================
--- parole/trunk/data/interfaces/parole.ui	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/data/interfaces/parole.ui	2009-07-23 21:35:01 UTC (rev 7778)
@@ -5,7 +5,7 @@
   <object class="GtkWindow" id="main-window">
     <property name="window_position">center</property>
     <property name="default_width">780</property>
-    <property name="default_height">440</property>
+    <property name="default_height">480</property>
     <signal name="destroy" handler="parole_player_destroy_cb"/>
     <signal name="key_press_event" handler="parole_player_key_press"/>
     <signal name="delete_event" handler="parole_player_delete_event_cb"/>
@@ -25,12 +25,12 @@
                   <object class="GtkMenu" id="media-menu">
                     <property name="visible">True</property>
                     <child>
-                      <object class="GtkImageMenuItem" id="menu-open">
+                      <object class="GtkImageMenuItem" id="menu-add">
                         <property name="label">gtk-open</property>
                         <property name="visible">True</property>
                         <property name="use_underline">True</property>
                         <property name="use_stock">True</property>
-                        <signal name="activate" handler="parole_player_menu_open_cb"/>
+                        <signal name="activate" handler="parole_player_menu_add_cb"/>
                       </object>
                     </child>
                     <child>
@@ -44,15 +44,6 @@
                       </object>
                     </child>
                     <child>
-                      <object class="GtkImageMenuItem" id="menu-add">
-                        <property name="label">gtk-add</property>
-                        <property name="visible">True</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_stock">True</property>
-                        <signal name="activate" handler="parole_player_menu_add_cb"/>
-                      </object>
-                    </child>
-                    <child>
                       <object class="GtkSeparatorMenuItem" id="separatormenuitem1">
                         <property name="visible">True</property>
                       </object>
@@ -168,7 +159,6 @@
                 <child>
                   <object class="GtkNotebook" id="notebook">
                     <property name="visible">True</property>
-                    <property name="show_tabs">False</property>
                     <property name="scrollable">True</property>
                     <property name="group_id">0</property>
                     <child>

Modified: parole/trunk/data/interfaces/playlist.ui
===================================================================
--- parole/trunk/data/interfaces/playlist.ui	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/data/interfaces/playlist.ui	2009-07-23 21:35:01 UTC (rev 7778)
@@ -46,8 +46,23 @@
           </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>
@@ -55,12 +70,13 @@
           </object>
           <packing>
             <property name="expand">False</property>
-            <property name="position">1</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>
@@ -68,12 +84,13 @@
           </object>
           <packing>
             <property name="expand">False</property>
-            <property name="position">2</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>
@@ -81,7 +98,7 @@
           </object>
           <packing>
             <property name="expand">False</property>
-            <property name="position">3</property>
+            <property name="position">4</property>
           </packing>
         </child>
       </object>
@@ -108,4 +125,8 @@
     <property name="visible">True</property>
     <property name="stock">gtk-go-down</property>
   </object>
+  <object class="GtkImage" id="image5">
+    <property name="visible">True</property>
+    <property name="stock">gtk-save-as</property>
+  </object>
 </interface>

Added: parole/trunk/data/interfaces/save-playlist.ui
===================================================================
--- parole/trunk/data/interfaces/save-playlist.ui	                        (rev 0)
+++ parole/trunk/data/interfaces/save-playlist.ui	2009-07-23 21:35:01 UTC (rev 7778)
@@ -0,0 +1,128 @@
+<?xml version="1.0"?>
+<interface>
+  <requires lib="gtk+" version="2.16"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkListStore" id="liststore">
+    <columns>
+      <!-- column-name filetype -->
+      <column type="gchararray"/>
+      <!-- column-name extension -->
+      <column type="gchararray"/>
+      <!-- column-name extension_id -->
+      <column type="guint"/>
+    </columns>
+    <data>
+      <row>
+        <col id="0" translatable="yes">By Extension</col>
+        <col id="1" translatable="yes"></col>
+        <col id="2">0</col>
+      </row>
+    </data>
+  </object>
+  <object class="GtkFileChooserDialog" id="filechooserdialog">
+    <property name="border_width">5</property>
+    <property name="default_width">480</property>
+    <property name="default_height">300</property>
+    <property name="type_hint">normal</property>
+    <property name="has_separator">False</property>
+    <property name="action">save</property>
+    <child internal-child="vbox">
+      <object class="GtkVBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child>
+          <object class="GtkExpander" id="expander1">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <child>
+              <object class="GtkTreeView" id="treeview">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="model">liststore</property>
+                <signal name="cursor_changed" handler="parole_media_list_format_cursor_changed_cb"/>
+                <child>
+                  <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+                    <property name="title">File Type</property>
+                    <property name="expand">True</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                      <attributes>
+                        <attribute name="text">0</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+                    <property name="title">Extension</property>
+                    <child>
+                      <object class="GtkCellRendererText" id="cellrenderertext2"/>
+                      <attributes>
+                        <attribute name="text">1</attribute>
+                      </attributes>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child type="label">
+              <object class="GtkLabel" id="label1">
+                <property name="visible">True</property>
+                <property name="label" translatable="yes">Select File Types (By Extension)</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkHButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="button2">
+                <property name="label" translatable="no">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="parole_media_list_close_save_dialog_cb"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="button1">
+                <property name="label" translatable="no">gtk-save</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="use_stock">True</property>
+                <signal name="clicked" handler="parole_media_list_save_playlist_cb"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="0">button2</action-widget>
+      <action-widget response="0">button1</action-widget>
+    </action-widgets>
+  </object>
+</interface>

Modified: parole/trunk/data/mime/mime-type-list.txt
===================================================================
--- parole/trunk/data/mime/mime-type-list.txt	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/data/mime/mime-type-list.txt	2009-07-23 21:35:01 UTC (rev 7778)
@@ -15,7 +15,6 @@
 application/x-quicktimeplayer
 application/x-shorten
 application/x-smil
-application/xspf+xml
 audio/3gpp
 audio/ac3
 audio/AMR
@@ -24,7 +23,6 @@
 audio/midi
 audio/mp4
 audio/mpeg
-audio/mpegurl
 audio/ogg
 audio/vnd.rn-realaudio
 audio/x-ape
@@ -35,11 +33,6 @@
 audio/x-mod
 audio/x-mp3
 audio/x-mpeg
-audio/x-mpegurl
-audio/x-ms-asf
-audio/x-ms-asx
-audio/x-ms-wax
-audio/x-ms-wma
 audio/x-musepack
 audio/x-pn-aiff
 audio/x-pn-au
@@ -50,7 +43,6 @@
 audio/x-realaudio
 audio/x-real-audio
 audio/x-sbc
-audio/x-scpls
 audio/x-speex
 audio/x-tta
 audio/x-wav
@@ -90,8 +82,6 @@
 video/x-msvideo
 video/x-ms-wm
 video/x-ms-wmv
-video/x-ms-wmx
-video/x-ms-wvx
 video/x-nsv
 video/x-ogm+ogg
 video/x-theora+ogg

Modified: parole/trunk/parole/Makefile.am
===================================================================
--- parole/trunk/parole/Makefile.am	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/Makefile.am	2009-07-23 21:35:01 UTC (rev 7778)
@@ -5,7 +5,6 @@
 
 INCLUDES =					\
 	-I$(top_srcdir)				\
-	-I$(top_srcdir)/common			\
 	-I$(top_srcdir)/data			\
 	-I$(top_srcdir)/data/mime		\
 	-DLOCALEDIR=\"$(localedir)\"		\
@@ -30,7 +29,6 @@
 	-export-symbols-regex "^[[^_]].*"
 
 PAROLE_LIBS = 					\
-	$(top_srcdir)/common/libparolecommon.la \
 	$(GTK_LIBS)                             \
         $(GLIB_LIBS)                            \
         $(GOBJECT_LIBS)                         \
@@ -54,7 +52,7 @@
 INST_HFILES =					\
 	parole.h				\
 	parole-plugin.h				\
-	parole-mediafile.h			\
+	parole-file.h				\
 	parole-stream.h
 
 NOINST_HFILES =					\
@@ -62,7 +60,6 @@
 	parole-gst.h				\
 	parole-vis.h				\
 	parole-statusbar.h			\
-	parole-sidebar.h			\
 	parole-mediachooser.h			\
 	parole-filters.h			\
 	parole-screensaver.h			\
@@ -75,7 +72,10 @@
 	parole-medialist.h			\
 	parole-debug.h				\
 	parole-plugins-manager.h		\
-	parole-module.h	
+	parole-module.h				\
+	parole-pl-parser.h			\
+	parole-about.h				\
+	parole-builder.h
 
 libparole_headers =				\
 	$(INST_HFILES)
@@ -93,9 +93,8 @@
 	parole-player.c				\
 	parole-gst.c				\
 	parole-stream.c				\
-	parole-mediafile.c			\
+	parole-file.c				\
 	parole-vis.c				\
-	parole-sidebar.c			\
 	parole-statusbar.c			\
 	parole-medialist.c			\
 	parole-mediachooser.c			\
@@ -110,7 +109,10 @@
 	parole-debug.c				\
 	parole-plugins-manager.c		\
 	parole-plugin.c				\
-	parole-module.c
+	parole-module.c				\
+	parole-pl-parser.c			\
+	parole-about.c				\
+	parole-builder.c
 
 libparole_la_LDFLAGS =				\
 	$(PAROLE_LDFLAGS)
@@ -130,7 +132,8 @@
 
 parole_glib_enum_headers =			\
 	parole-gst.h				\
-	parole-plugin.h
+	parole-plugin.h				\
+	parole-pl-parser.h
 
 if MAINTAINER_MODE
 
@@ -162,6 +165,7 @@
 		--fhead "#include \"enum-gtypes.h\"\n\n" \
 		--fhead "#include \"parole-gst.h\"\n\n" \
 		--fhead "#include \"parole-plugin.h\"\n\n" \
+		--fhead "#include \"parole-pl-parser.h\"\n\n" \
 		--fprod "\n/* enumerations from \"@filename@\" */" \
 		--vhead "GType\n at enum_name@_get_type (void)\n{\n  static GType etype = 0;\n  if (etype == 0) {\n    static const G at Type@Value values[] = {" \
 		--vprod "      { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \

Added: parole/trunk/parole/parole-about.c
===================================================================
--- parole/trunk/parole/parole-about.c	                        (rev 0)
+++ parole/trunk/parole/parole-about.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -0,0 +1,80 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at xfce.org>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libxfce4util/libxfce4util.h>
+
+#include "parole-about.h"
+
+static void
+parole_link_browser (GtkAboutDialog *about, const gchar *link, gpointer data)
+{
+    gchar *cmd = g_strdup_printf ("%s %s", "xdg-open", link);
+    g_spawn_command_line_async (cmd, NULL);
+    g_free (cmd);
+}
+
+static void
+parole_link_mailto (GtkAboutDialog *about, const gchar *link, gpointer data)
+{
+    gchar *cmd = g_strdup_printf( "%s %s", "xdg-email", link);
+
+    g_spawn_command_line_async (cmd, NULL);
+    
+    g_free (cmd);
+}
+
+void  parole_about (const gchar *package)
+{
+    const gchar* authors[3] = 
+    {
+	"Ali Abdallah <aliov at xfce.org>", 
+	 NULL
+    };
+							    
+    static const gchar *documenters[] =
+    {
+	"Ali Abdallah <aliov at xfce.org>",
+	NULL,
+    };
+    
+
+    gtk_about_dialog_set_url_hook (parole_link_browser, NULL, NULL);
+    gtk_about_dialog_set_email_hook (parole_link_mailto, NULL, NULL);
+    
+    gtk_show_about_dialog (NULL,
+		           "authors", authors,
+			   "copyright", "Copyright \302\251 2009 Ali Abdallah",
+			   "destroy-with-parent", TRUE,
+			   "documenters", documenters,
+			   "license", XFCE_LICENSE_GPL,
+			   "name", package,
+			   "translator-credits", _("translator-credits"),
+			   "version", PACKAGE_VERSION,
+			   "website", "http://goodies.xfce.org",
+			   NULL);
+}

Added: parole/trunk/parole/parole-about.h
===================================================================
--- parole/trunk/parole/parole-about.h	                        (rev 0)
+++ parole/trunk/parole/parole-about.h	2009-07-23 21:35:01 UTC (rev 7778)
@@ -0,0 +1,29 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at xfce.org>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __PAROLE_ABOUT_H
+#define __PAROLE_ABOUT_H
+
+#include <gtk/gtk.h>
+
+void 		parole_about	(const gchar *package);
+
+
+#endif /* __PAROLE_ABOUT_H */

Added: parole/trunk/parole/parole-builder.c
===================================================================
--- parole/trunk/parole/parole-builder.c	                        (rev 0)
+++ parole/trunk/parole/parole-builder.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -0,0 +1,86 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at xfce.org>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interfaces/parole_ui.h"
+#include "parole-builder.h"
+
+GtkBuilder *
+parole_builder_get_main_interface (void)
+{
+    static gpointer parole_builder_object = NULL;
+    
+    if ( G_LIKELY (parole_builder_object != NULL) )
+    {
+	g_object_ref (parole_builder_object);
+    }
+    else
+    {
+	parole_builder_object = parole_builder_new_from_string (parole_ui, parole_ui_length);
+	g_object_add_weak_pointer (parole_builder_object, &parole_builder_object);
+    }
+    
+    return GTK_BUILDER (parole_builder_object);
+}
+
+GtkBuilder *parole_builder_new_from_file (const gchar *file)
+{
+    GtkBuilder *builder;
+    GError *error = NULL;
+
+    builder = gtk_builder_new ();
+    
+    gtk_builder_add_from_file (GTK_BUILDER (builder),
+			       file,
+			       &error);
+			       
+    if ( error )
+    {
+	g_critical ("%s", error->message);
+	g_error_free (error);
+    }
+    
+    return builder;
+}
+
+GtkBuilder *parole_builder_new_from_string (const gchar *ui, gsize length)
+{
+    GError *error = NULL;
+    GtkBuilder *builder;
+    
+    builder = gtk_builder_new ();
+    
+    gtk_builder_add_from_string (builder, ui, length, &error);
+    
+    if ( error )
+    {
+	g_critical ("%s", error->message);
+	g_error_free (error);
+    }
+    
+    return builder;
+}

Added: parole/trunk/parole/parole-builder.h
===================================================================
--- parole/trunk/parole/parole-builder.h	                        (rev 0)
+++ parole/trunk/parole/parole-builder.h	2009-07-23 21:35:01 UTC (rev 7778)
@@ -0,0 +1,38 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at xfce.org>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __PAROLE_BUILDER_H
+#define __PAROLE_BUILDER_H
+
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+GtkBuilder       	       *parole_builder_get_main_interface       (void);
+
+GtkBuilder		       *parole_builder_new_from_file   		(const gchar *file);
+
+GtkBuilder		       *parole_builder_new_from_string 		(const gchar *ui,
+									 gsize length);
+
+G_END_DECLS
+
+#endif /* __PAROLE_BUILDER_H */

Modified: parole/trunk/parole/parole-conf-dialog.c
===================================================================
--- parole/trunk/parole/parole-conf-dialog.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-conf-dialog.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -26,9 +26,9 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "common/parole-builder.h"
 #include "interfaces/parole-settings_ui.h"
 
+#include "parole-builder.h"
 #include "parole-conf-dialog.h"
 #include "parole-conf.h"
 #include "parole-vis.h"

Modified: parole/trunk/parole/parole-debug.h
===================================================================
--- parole/trunk/parole/parole-debug.h	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-debug.h	2009-07-23 21:35:01 UTC (rev 7778)
@@ -63,4 +63,4 @@
 
 G_END_DECLS
 
-#endif /* __XFPM_DEBUG_H */
+#endif /* __PAROLE_DEBUG_H */

Modified: parole/trunk/parole/parole-disc.c
===================================================================
--- parole/trunk/parole/parole-disc.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-disc.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -31,9 +31,8 @@
 
 #include <libxfce4util/libxfce4util.h>
 
-#include "common/parole-builder.h"
-
 #include "parole-disc.h"
+#include "parole-builder.h"
 
 static void parole_disc_finalize   (GObject *object);
 

Copied: parole/trunk/parole/parole-file.c (from rev 7735, parole/trunk/parole/parole-mediafile.c)
===================================================================
--- parole/trunk/parole/parole-file.c	                        (rev 0)
+++ parole/trunk/parole/parole-file.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -0,0 +1,351 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at xfce.org>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "parole-file.h"
+
+#define PAROLE_FILE_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_FILE, ParoleFilePrivate))
+
+typedef struct _ParoleFilePrivate ParoleFilePrivate;
+
+struct _ParoleFilePrivate
+{
+    gchar 	*filename;
+    gchar 	*display_name;
+    gchar 	*uri;
+    gchar       *content_type;
+    
+};
+
+enum
+{
+    PROP_0,
+    PROP_PATH,
+    PROP_DISPLAY_NAME,
+    PROP_URI,
+    PROP_CONTENT_TYPE
+};
+
+G_DEFINE_TYPE (ParoleFile, parole_file, G_TYPE_OBJECT)
+
+static void
+parole_file_finalize (GObject *object)
+{
+    ParoleFile *file;
+    ParoleFilePrivate *priv;
+
+    file = PAROLE_FILE (object);
+    priv = PAROLE_FILE_GET_PRIVATE (file);
+    
+    g_debug ("File object finalized %s", priv->display_name);
+    
+    if ( priv->filename )
+	g_free (priv->filename);
+
+    if ( priv->uri )
+	g_free (priv->uri);
+	
+    if ( priv->display_name )
+	g_free (priv->display_name);
+	
+    if ( priv->content_type )
+	g_free (priv->content_type);
+    
+    G_OBJECT_CLASS (parole_file_parent_class)->finalize (object);
+}
+
+static void
+parole_file_set_property (GObject *object, guint prop_id, 
+			      const GValue *value, GParamSpec *pspec)
+{
+    ParoleFile *file;
+    file = PAROLE_FILE (object);
+    
+    switch (prop_id)
+    {
+	case PROP_PATH:
+	    PAROLE_FILE_GET_PRIVATE (file)->filename = g_value_dup_string (value);
+	    break;
+	case PROP_DISPLAY_NAME:
+	    PAROLE_FILE_GET_PRIVATE (file)->display_name = g_value_dup_string (value);
+	    break;
+	default:
+	    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	    break;
+    }
+}
+
+static void
+parole_file_get_property (GObject *object, guint prop_id, 
+			      GValue *value, GParamSpec *pspec)
+{
+    ParoleFile *file;
+
+    file = PAROLE_FILE (object);
+    
+    switch (prop_id)
+    {
+	case PROP_PATH:
+	    g_value_set_string (value, PAROLE_FILE_GET_PRIVATE (file)->filename);
+	    break;
+	case PROP_URI:
+	    g_value_set_string (value, PAROLE_FILE_GET_PRIVATE (file)->filename);
+	    break;
+	case PROP_CONTENT_TYPE:
+	    g_value_set_string (value, PAROLE_FILE_GET_PRIVATE (file)->content_type);
+	    break;
+	case PROP_DISPLAY_NAME:
+	    g_value_set_string (value, PAROLE_FILE_GET_PRIVATE (file)->display_name);
+	    break;
+	default:
+	    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+	    break;
+    }
+}
+
+static void
+parole_file_constructed (GObject *object)
+{
+    GFile *gfile;
+    GFileInfo *info;
+    ParoleFile *file;
+    ParoleFilePrivate *priv;
+    GError *error = NULL;
+    
+    file = PAROLE_FILE (object);
+    priv = PAROLE_FILE_GET_PRIVATE (file);
+    
+    gfile = g_file_new_for_commandline_arg (priv->filename);
+
+    info = g_file_query_info (gfile, 
+			      "standard::*,",
+			      0,
+			      NULL,
+			      &error);
+
+    if ( error )
+    {
+	if ( G_LIKELY (error->code == G_IO_ERROR_NOT_SUPPORTED) )
+	{
+	    g_error_free (error);
+	    if ( !priv->display_name )
+	        priv->display_name = g_file_get_basename (gfile);
+	}
+	else
+	{
+	    priv->display_name = g_strdup (priv->filename);
+	}
+	g_warning ("Unable to read file info %s", error->message);
+	goto out;
+    }
+
+    if (!priv->display_name)
+	priv->display_name = g_strdup (g_file_info_get_display_name (info));
+
+    priv->content_type = g_strdup (g_file_info_get_content_type (info));
+    
+    g_object_unref (info);
+out:
+    priv->uri = g_file_get_uri (gfile);
+    g_object_unref (gfile);
+}
+
+static void
+parole_file_class_init (ParoleFileClass *klass)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+    object_class->finalize = parole_file_finalize;
+    
+    object_class->constructed = parole_file_constructed;
+    object_class->set_property = parole_file_set_property;
+    object_class->get_property = parole_file_get_property;
+
+    /**
+     * ParoleFile:filename:
+     * 
+     * The filename of the file.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_PATH,
+				     g_param_spec_string ("filename",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_CONSTRUCT_ONLY|
+							  G_PARAM_READWRITE));
+
+    /**
+     * ParoleFile:display-name:
+     * 
+     * a UTF-8 name that can be displayed in the UI.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_DISPLAY_NAME,
+				     g_param_spec_string ("display-name",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_CONSTRUCT_ONLY|
+							  G_PARAM_READWRITE));
+
+    /**
+     * ParoleFile:uri:
+     * 
+     * The Uri of the file.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_URI,
+				     g_param_spec_string ("uri",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_READABLE));
+
+    /**
+     * ParoleFile:content-type:
+     * 
+     * The content type of the file.
+     * 
+     * Since: 0.1 
+     **/
+    g_object_class_install_property (object_class,
+				     PROP_CONTENT_TYPE,
+				     g_param_spec_string ("content-type",
+							  NULL, NULL,
+							  NULL,
+							  G_PARAM_READABLE));
+
+    g_type_class_add_private (klass, sizeof (ParoleFilePrivate));
+}
+
+static void
+parole_file_init (ParoleFile *file)
+{
+    ParoleFilePrivate *priv;
+    
+    priv = PAROLE_FILE_GET_PRIVATE (file);
+
+    priv->filename         = NULL;
+    priv->display_name = NULL;
+    priv->uri          = NULL;
+    priv->content_type    = NULL;
+}
+
+/**
+ * parole_file_new:
+ * @filename: filename.
+ * 
+ * 
+ * 
+ * Returns: A new #ParoleFile object.
+ **/
+ParoleFile *
+parole_file_new (const gchar *filename)
+{
+    ParoleFile *file = NULL;
+    file = g_object_new (PAROLE_TYPE_FILE, "filename", filename, NULL);
+    return file;
+}
+
+ParoleFile *
+parole_file_new_with_display_name (const gchar *filename, const gchar *display_name)
+{
+    ParoleFile *file = NULL;
+    file = g_object_new (PAROLE_TYPE_FILE, 
+			 "filename", filename, 
+			 "display-name", display_name, 
+			 NULL);
+    return file;
+}
+
+/**
+ * parole_file_get_file_name:
+ * @file: a #ParoleFile.
+ *  
+ * 
+ * Returns: A string containing the file name.
+ **/
+const gchar *
+parole_file_get_file_name (const ParoleFile *file)
+{
+    g_return_val_if_fail (PAROLE_IS_FILE (file), NULL);
+    
+    return PAROLE_FILE_GET_PRIVATE (file)->filename;
+}
+
+/**
+ * parole_file_get_display_name:
+ * @file: a #ParoleFile.
+ *  
+ * 
+ * Returns: A string containing the display name.
+ **/
+const gchar *
+parole_file_get_display_name (const ParoleFile *file)
+{
+    g_return_val_if_fail (PAROLE_IS_FILE (file), NULL);
+    
+    return PAROLE_FILE_GET_PRIVATE (file)->display_name;
+}
+
+/**
+ * parole_file_get_uri:
+ * @file: a #ParoleFile.
+ *  
+ * 
+ * Returns: A string containing the file uri.
+ **/
+const gchar *
+parole_file_get_uri (const ParoleFile *file)
+{
+    g_return_val_if_fail (PAROLE_IS_FILE (file), NULL);
+    
+    return PAROLE_FILE_GET_PRIVATE (file)->uri;
+}
+
+/**
+ * parole_file_get_content_type:
+ * @file: a #ParoleFile.
+ *  
+ * 
+ * Returns: A string containing the content type of the file.
+ **/
+const gchar *
+parole_file_get_content_type (const ParoleFile *file) 
+{
+    g_return_val_if_fail (PAROLE_IS_FILE (file), NULL);
+    
+    return PAROLE_FILE_GET_PRIVATE (file)->content_type;
+}


Property changes on: parole/trunk/parole/parole-file.c
___________________________________________________________________
Added: svn:mergeinfo
   + 

Copied: parole/trunk/parole/parole-file.h (from rev 7735, parole/trunk/parole/parole-mediafile.h)
===================================================================
--- parole/trunk/parole/parole-file.h	                        (rev 0)
+++ parole/trunk/parole/parole-file.h	2009-07-23 21:35:01 UTC (rev 7778)
@@ -0,0 +1,62 @@
+/*
+ * * Copyright (C) 2009 Ali <aliov at xfce.org>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __PAROLE_MEDIA_FILE_H
+#define __PAROLE_MEDIA_FILE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define PAROLE_TYPE_FILE        (parole_file_get_type () )
+#define PAROLE_FILE(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), PAROLE_TYPE_FILE, ParoleFile))
+#define PAROLE_IS_FILE(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), PAROLE_TYPE_FILE))
+
+typedef struct _ParoleFile      ParoleFile;
+typedef struct _ParoleFileClass ParoleFileClass;
+
+struct _ParoleFile
+{
+    GObject         		parent;
+};
+
+struct _ParoleFileClass
+{
+    GObjectClass 		parent_class;
+};
+
+GType        			parole_file_get_type        	  (void) G_GNUC_CONST;
+
+ParoleFile       	       *parole_file_new             	  (const gchar *filename);
+
+ParoleFile       	       *parole_file_new_with_display_name (const gchar *filename,
+								   const gchar *display_name);
+
+const gchar   G_CONST_RETURN   *parole_file_get_file_name 	  (const ParoleFile *file) G_GNUC_PURE;
+
+const gchar   G_CONST_RETURN   *parole_file_get_display_name 	  (const ParoleFile *file) G_GNUC_PURE;
+
+const gchar   G_CONST_RETURN   *parole_file_get_uri 		  (const ParoleFile *file) G_GNUC_PURE;
+
+const gchar   G_CONST_RETURN   *parole_file_get_content_type      (const ParoleFile *file) G_GNUC_PURE;
+
+G_END_DECLS
+
+#endif /* __PAROLE_MEDIA_FILE_H */


Property changes on: parole/trunk/parole/parole-file.h
___________________________________________________________________
Added: svn:mergeinfo
   + 

Modified: parole/trunk/parole/parole-filters.c
===================================================================
--- parole/trunk/parole/parole-filters.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-filters.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -31,8 +31,19 @@
 
 #include "parole-filters.h"
 #include "parole-utils.h"
+#include "parole-pl-parser.h"
 #include "data/mime/parole-mime-types.h"
 
+static char *playlist_mime_types[] = {
+    "text/plain",
+    "audio/x-mpegurl",
+    "audio/playlist",
+    "audio/x-scpls",
+    "audio/x-ms-asx",
+    "application/xml",
+    "application/xspf+xml",
+};
+
 /*
  * Supported Audio formats.
  */
@@ -90,14 +101,45 @@
     return filter;
 }
 
-gboolean parole_file_filter (GtkFileFilter *filter, ParoleMediaFile *file)
+GtkFileFilter *parole_get_supported_files_filter (void)
 {
+    GtkFileFilter *filter;
+    guint i;
+    
+    filter = parole_get_supported_media_filter ();
+    
+    gtk_file_filter_set_name (filter, _("All supported files"));
+    
+    for ( i = 0; i < G_N_ELEMENTS (playlist_mime_types); i++)
+	gtk_file_filter_add_mime_type (filter, playlist_mime_types[i]);
+    
+    return filter;
+    
+}
+
+GtkFileFilter 	*parole_get_supported_playlist_filter	(void)
+{
+    GtkFileFilter *filter;
+    guint i;
+    
+    filter = gtk_file_filter_new ();
+    
+    gtk_file_filter_set_name (filter, _("Playlist files"));
+    
+    for ( i = 0; i < G_N_ELEMENTS (playlist_mime_types); i++)
+	gtk_file_filter_add_mime_type (filter, playlist_mime_types[i]);
+    
+    return filter;
+}
+
+gboolean parole_file_filter (GtkFileFilter *filter, ParoleFile *file)
+{
     GtkFileFilterInfo filter_info;
 
     gboolean ret;
     
-    filter_info.display_name = parole_media_file_get_display_name (file);
-    filter_info.mime_type = parole_media_file_get_content_type (file);
+    filter_info.display_name = parole_file_get_display_name (file);
+    filter_info.mime_type = parole_file_get_content_type (file);
     
     filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME | GTK_FILE_FILTER_MIME_TYPE;
     
@@ -108,16 +150,32 @@
 
 void parole_get_media_files (GtkFileFilter *filter, const gchar *path, GSList **list)
 {
+    GtkFileFilter *playlist_filter;
     GSList *list_internal = NULL;
+    GSList *playlist = NULL;
     GDir *dir;
     const gchar *name;
-    ParoleMediaFile *file;
+    ParoleFile *file;
 
+    playlist_filter = parole_get_supported_playlist_filter ();
+    g_object_ref_sink (playlist_filter);
+
     if ( g_file_test (path, G_FILE_TEST_IS_REGULAR ) )
     {
-	file = parole_media_file_new (path);
-	if ( parole_file_filter (filter, file) )
+	file = parole_file_new (path);
+	if ( parole_file_filter (playlist_filter, file) )
+	{
+	    playlist = parole_pl_parser_load_file (path);
+	    g_object_unref (file);
+	    if ( playlist)
+	    {
+		*list = g_slist_concat (*list, playlist);
+	    }
+	}
+	else if ( parole_file_filter (filter, file) )
+	{
 	    *list = g_slist_append (*list, file);
+	}
 	else
 	    g_object_unref (file);
     }
@@ -137,9 +195,20 @@
 	    }
 	    else if ( g_file_test (path_internal, G_FILE_TEST_IS_REGULAR) )
 	    {
-		file = parole_media_file_new (path_internal);
-		if ( parole_file_filter (filter, file) )
+		file = parole_file_new (path_internal);
+		if ( parole_file_filter (playlist_filter, file) )
+		{
+		    playlist = parole_pl_parser_load_file (path);
+		    g_object_unref (file);
+		    if ( playlist)
+		    {
+			*list = g_slist_concat (*list, playlist);
+		    }
+		}
+		else if ( parole_file_filter (filter, file) )
+		{
 		    list_internal = g_slist_append (list_internal, file);
+		}
 		else
 		    g_object_unref (file);
 	    }
@@ -149,4 +218,6 @@
 	g_dir_close (dir);
 	*list = g_slist_concat (*list, list_internal);
     }
+    
+    g_object_unref (playlist_filter);
 }

Modified: parole/trunk/parole/parole-filters.h
===================================================================
--- parole/trunk/parole/parole-filters.h	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-filters.h	2009-07-23 21:35:01 UTC (rev 7778)
@@ -22,19 +22,39 @@
 #define __PAROLE_FILTERS_H
 
 #include <gtk/gtk.h>
-#include "parole-mediafile.h"
 
+#include "parole-file.h"
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+    PAROLE_FILE_UNKNOWN,
+    PAROLE_FILE_AUDIO,
+    PAROLE_FILE_VIDEO,
+    PAROLE_FILE_PLAYLIST
+    
+} ParoleFileFormat;
+
 GtkFileFilter 		*parole_get_supported_audio_filter	(void);
 
 GtkFileFilter 		*parole_get_supported_video_filter	(void);
 
 GtkFileFilter 		*parole_get_supported_media_filter	(void);
 
+GtkFileFilter 		*parole_get_supported_files_filter	(void);
+
+GtkFileFilter 		*parole_get_supported_playlist_filter	(void);
+
 gboolean		 parole_file_filter			(GtkFileFilter *filter,
-								 ParoleMediaFile *file);
+								 ParoleFile *file);
 
+ParoleFileFormat	 parole_file_guess_format		(ParoleFile *file);
+
 void			 parole_get_media_files			(GtkFileFilter *filter,
 								 const gchar *path,
 								 GSList **list);
 
+G_END_DECLS
+
 #endif /* PAROLE_FILTERS_H */

Modified: parole/trunk/parole/parole-gst.c
===================================================================
--- parole/trunk/parole/parole-gst.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-gst.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -327,11 +327,13 @@
     
     if ( G_UNLIKELY (format != GST_FORMAT_TIME ) )
 	goto out;
-	
-    value = ( pos / ((gdouble) 60 * 1000 * 1000 * 1000 ));
-    
-    g_signal_emit (G_OBJECT (gst), signals [MEDIA_PROGRESSED], 0, gst->priv->stream, value);
 
+    if ( gst->priv->state == GST_STATE_PLAYING )
+    {
+	value = ( pos / ((gdouble) 60 * 1000 * 1000 * 1000 ));
+	g_signal_emit (G_OBJECT (gst), signals [MEDIA_PROGRESSED], 0, gst->priv->stream, value);
+    }
+
 out:
     if ( g_timer_elapsed (gst->priv->hidecursor_timer, NULL ) > HIDE_WINDOW_CURSOR_TIMEOUT )
 	parole_gst_set_cursor_visible (gst, FALSE);

Modified: parole/trunk/parole/parole-mediachooser.c
===================================================================
--- parole/trunk/parole/parole-mediachooser.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-mediachooser.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -32,18 +32,16 @@
 #include <libxfce4util/libxfce4util.h>
 #include <libxfcegui4/libxfcegui4.h>
 
-#include "common/parole-builder.h"
 #include "interfaces/mediachooser_ui.h"
 #include "interfaces/openlocation_ui.h"
 
 #include "parole-mediachooser.h"
-
-#include "parole-mediafile.h"
+#include "parole-builder.h"
+#include "parole-file.h"
 #include "parole-filters.h"
 #include "parole-rc-utils.h"
 #include "parole-utils.h"
 
-
 /*
  * GtkBuilder Callbacks
  */
@@ -59,13 +57,9 @@
 void	parole_media_chooser_open_location_cb (GtkButton *bt, 
 					       ParoleMediaChooser *chooser);
 
-#define MEDIA_CHOOSER_INTERFACE_FILE INTERFACES_DIR "/mediachooser.ui"
-#define OPEN_LOCATION_INTERFACE_FILE INTERFACES_DIR "/openlocation.ui"
-
 enum
 {
     MEDIA_FILES_OPENED,
-    MEDIA_FILE_OPENED,
     LOCATION_OPENED,
     LAST_SIGNAL
 };
@@ -94,7 +88,7 @@
 }
 
 static void
-parole_media_chooser_add_many (ParoleMediaChooser *chooser, GtkWidget *file_chooser)
+parole_media_chooser_add (ParoleMediaChooser *chooser, GtkWidget *file_chooser)
 {
     GSList *files;
     GtkFileFilter *filter;
@@ -126,36 +120,13 @@
 void
 parole_media_chooser_open (GtkWidget *widget, ParoleMediaChooser *chooser)
 {
-    ParoleMediaFile *file;
     GtkWidget *file_chooser;
-    gboolean  multiple;
-    gchar *filename;
 
     file_chooser = GTK_WIDGET (g_object_get_data (G_OBJECT (chooser), "file-chooser"));
     
-    multiple = gtk_file_chooser_get_select_multiple (GTK_FILE_CHOOSER (file_chooser));
-    
-    /*
-     * Emit one file opened
-     */
-    if ( multiple == FALSE )
-    {
-	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_chooser));
-	
-	if ( G_LIKELY (filename != NULL ) )
-	{
-	    file = parole_media_file_new (filename);
-	    g_signal_emit (G_OBJECT (chooser), signals [MEDIA_FILE_OPENED], 0, file);
-	    g_free (filename);
-	}
-	parole_media_chooser_close (NULL, chooser);
-    }
-    else
-    {
-	parole_window_busy_cursor (GTK_WIDGET (chooser)->window);
-	parole_media_chooser_add_many (chooser, file_chooser);
-	parole_media_chooser_close (NULL, chooser);
-    }
+    parole_window_busy_cursor (GTK_WIDGET (chooser)->window);
+    parole_media_chooser_add (chooser, file_chooser);
+    parole_media_chooser_close (NULL, chooser);
 }
 
 void
@@ -180,7 +151,7 @@
 }
 
 static void
-parole_media_chooser_open_internal (GtkWidget *chooser, gboolean multiple)
+parole_media_chooser_open_internal (GtkWidget *chooser)
 {
     ParoleMediaChooser *media_chooser;
     GtkWidget   *vbox;
@@ -199,24 +170,26 @@
     vbox = GTK_WIDGET (gtk_builder_get_object (builder, "vbox"));
     open = GTK_WIDGET (gtk_builder_get_object (builder, "open"));
     
-    gtk_window_set_title (GTK_WINDOW (chooser), multiple == TRUE ? _("Add media files") : _("Open media file"));
+    gtk_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 ());
     gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), parole_get_supported_video_filter ());
+    gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), parole_get_supported_playlist_filter ());
 
     folder = parole_rc_read_entry_string ("media-chooser-folder", NULL);
     
     if ( folder )
 	gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_chooser), folder);
     
-    gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (file_chooser), multiple);
+    gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (file_chooser), TRUE);
     
-    img = gtk_image_new_from_stock (multiple ? GTK_STOCK_ADD : GTK_STOCK_OPEN, GTK_ICON_SIZE_BUTTON);
+    img = gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
     
     g_object_set (G_OBJECT (open),
 		  "image", img,
-		  "label", multiple ? _("Add") : _("Open"),
+		  "label", _("Add"),
 		  NULL);
     
     g_object_set_data (G_OBJECT (chooser), "file-chooser", file_chooser);
@@ -277,15 +250,6 @@
                       g_cclosure_marshal_VOID__POINTER,
                       G_TYPE_NONE, 1, G_TYPE_POINTER);
 
-    signals[MEDIA_FILE_OPENED] = 
-        g_signal_new("media-file-opened",
-                      PAROLE_TYPE_MEDIA_CHOOSER,
-                      G_SIGNAL_RUN_LAST,
-                      G_STRUCT_OFFSET (ParoleMediaChooserClass, media_file_opened),
-                      NULL, NULL,
-                      g_cclosure_marshal_VOID__OBJECT,
-                      G_TYPE_NONE, 1, G_TYPE_OBJECT);
-
     signals[LOCATION_OPENED] = 
         g_signal_new("location-opened",
                       PAROLE_TYPE_MEDIA_CHOOSER,
@@ -317,13 +281,13 @@
     return GTK_WIDGET (chooser);
 }
 
-GtkWidget *parole_media_chooser_open_local (GtkWidget *parent, gboolean multiple)
+GtkWidget *parole_media_chooser_open_local (GtkWidget *parent)
 {
     GtkWidget *dialog;
     
     dialog = parole_media_chooser_new (parent);
 	
-    parole_media_chooser_open_internal (dialog, multiple);
+    parole_media_chooser_open_internal (dialog);
     gtk_window_set_default_size (GTK_WINDOW (dialog), 680, 480);
     
     return dialog;

Modified: parole/trunk/parole/parole-mediachooser.h
===================================================================
--- parole/trunk/parole/parole-mediachooser.h	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-mediachooser.h	2009-07-23 21:35:01 UTC (rev 7778)
@@ -24,8 +24,6 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include "parole-mediafile.h"
-
 G_BEGIN_DECLS
 
 #define PAROLE_TYPE_MEDIA_CHOOSER        (parole_media_chooser_get_type () )
@@ -47,9 +45,6 @@
     void			 (*media_files_opened)		    (ParoleMediaChooser *chooser,
 								     GPtrArray *array);
 								     
-    void			 (*media_file_opened)		    (ParoleMediaChooser *chooser,
-								     ParoleMediaFile *file);
-								     
     void			 (*location_opened)		    (ParoleMediaChooser *chooser,
 								     const gchar *address);
     
@@ -57,8 +52,7 @@
 
 GType        			 parole_media_chooser_get_type      (void) G_GNUC_CONST;
 
-GtkWidget			*parole_media_chooser_open_local    (GtkWidget *parent,
-								     gboolean multiple);
+GtkWidget			*parole_media_chooser_open_local    (GtkWidget *parent);
 								     
 GtkWidget			*parole_media_chooser_open_location (GtkWidget *parent);
 

Modified: parole/trunk/parole/parole-medialist.c
===================================================================
--- parole/trunk/parole/parole-medialist.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-medialist.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -28,22 +28,45 @@
 
 #include <gtk/gtk.h>
 #include <glib.h>
+#include <glib/gstdio.h>
 #include <gio/gio.h>
 
 #include <libxfce4util/libxfce4util.h>
 #include <libxfcegui4/libxfcegui4.h>
 
-#include "common/parole-builder.h"
 #include "interfaces/playlist_ui.h"
+#include "interfaces/save-playlist_ui.h"
 
+#include "parole-builder.h"
 #include "parole-medialist.h"
-#include "parole-mediafile.h"
+#include "parole-file.h"
 #include "parole-mediachooser.h"
 
 #include "parole-filters.h"
+#include "parole-pl-parser.h"
 #include "parole-utils.h"
 #include "parole-dbus.h"
 
+typedef struct
+{
+    GtkWidget *chooser;
+    GtkTreeSelection *sel;
+    ParoleMediaList *list;
+    
+} ParolePlaylistSave;
+
+static struct
+{
+    ParolePlFormat format;
+    gchar * ext;
+} playlist_format_map [] = {
+  { PAROLE_PL_FORMAT_UNKNOWN, ""      },
+  { PAROLE_PL_FORMAT_M3U,     ".m3u"  },
+  { PAROLE_PL_FORMAT_PLS,     ".pls"  },
+  { PAROLE_PL_FORMAT_ASX,     ".asx"  },
+  { PAROLE_PL_FORMAT_XSPF,    ".xspf" }
+};
+
 static void 	parole_media_list_dbus_class_init (ParoleMediaListClass *klass);
 static void 	parole_media_list_dbus_init 	  (ParoleMediaList      *list);
 
@@ -55,6 +78,9 @@
 							 
 void		parole_media_list_media_down_clicked_cb (GtkButton *button, 
 							 ParoleMediaList *list);
+
+void		parole_media_list_save_cb		(GtkButton *button,
+						         ParoleMediaList *list);
 							 
 void		parole_media_list_add_clicked_cb 	(GtkButton *button, 
 							 ParoleMediaList *list);
@@ -82,13 +108,19 @@
 							 guint info,
 							 guint drag_time,
 							 ParoleMediaList *list);
+
+void		parole_media_list_format_cursor_changed_cb (GtkTreeView *view,
+							    ParolePlaylistSave *data);
+							    
+void		parole_media_list_close_save_dialog_cb (GtkButton *button,
+						        ParolePlaylistSave *data);
+						    
+void		parole_media_list_save_playlist_cb     (GtkButton *button,
+						        ParolePlaylistSave *data);
 /*
  * End of GtkBuilder callbacks
  */
 
-
-#define PLAYLIST_FILE INTERFACES_DIR "/playlist.ui"
-
 #define PAROLE_MEDIA_LIST_GET_PRIVATE(o) \
 (G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_MEDIA_LIST, ParoleMediaListPrivate))
 
@@ -97,6 +129,11 @@
     GtkWidget 	  	*view;
     GtkWidget		*box;
     GtkListStore	*store;
+    
+    GtkWidget		*remove;
+    GtkWidget		*up;
+    GtkWidget		*down;
+    GtkWidget		*save;
 };
 
 enum
@@ -118,12 +155,22 @@
 G_DEFINE_TYPE (ParoleMediaList, parole_media_list, GTK_TYPE_VBOX)
 
 static void
-parole_media_list_add (ParoleMediaList *list, ParoleMediaFile *file, gboolean emit)
+parole_media_list_set_widget_sensitive (ParoleMediaList *list, gboolean sensitive)
 {
+    gtk_widget_set_sensitive (GTK_WIDGET (list->priv->up), sensitive);
+    gtk_widget_set_sensitive (GTK_WIDGET (list->priv->remove), sensitive);
+    gtk_widget_set_sensitive (GTK_WIDGET (list->priv->down), sensitive);
+    gtk_widget_set_sensitive (GTK_WIDGET (list->priv->save), sensitive);
+}
+
+static void
+parole_media_list_add (ParoleMediaList *list, ParoleFile *file, gboolean emit)
+{
     GtkListStore *list_store;
     GtkTreePath *path;
     GtkTreeRowReference *row;
     GtkTreeIter iter;
+    gint nch;
     
     list_store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (list->priv->view)));
     
@@ -131,7 +178,7 @@
     
     gtk_list_store_set (list_store, 
 			&iter, 
-			NAME_COL, parole_media_file_get_display_name (file),
+			NAME_COL, parole_file_get_display_name (file),
 			DATA_COL, file,
 			-1);
     
@@ -147,18 +194,23 @@
      * a reference anyway.
      */
     g_object_unref (file);
+    
+    nch = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (list->priv->store), NULL); 
+    if ( nch == 1 )
+    {
+	gtk_widget_set_sensitive (list->priv->up, FALSE);
+	gtk_widget_set_sensitive (list->priv->down, FALSE);
+	gtk_widget_set_sensitive (list->priv->save, TRUE);
+	gtk_widget_set_sensitive (list->priv->remove, TRUE);
+    }
+    else
+	parole_media_list_set_widget_sensitive (list, TRUE);
 }
 
 static void
-parole_media_list_file_opened_cb (ParoleMediaChooser *chooser, ParoleMediaFile *file, ParoleMediaList *list)
-{
-    parole_media_list_add (list, file, TRUE);
-}
-
-static void
 parole_media_list_files_opened_cb (ParoleMediaChooser *chooser, GSList *files, ParoleMediaList *list)
 {
-    ParoleMediaFile *file;
+    ParoleFile *file;
     guint len;
     guint i;
     
@@ -174,7 +226,7 @@
 static void
 parole_media_list_location_opened_cb (ParoleMediaChooser *chooser, const gchar *location, ParoleMediaList *list)
 {
-    ParoleMediaFile *file;
+    ParoleFile *file;
     
     if ( parole_is_uri_disc (location) )
     {
@@ -182,25 +234,20 @@
     }
     else
     {
-	file = parole_media_file_new (location);
+	file = parole_file_new (location);
 	parole_media_list_add (list, file, TRUE);
     }
 }
 
 static void
-parole_media_list_open_internal (ParoleMediaList *list, gboolean multiple)
+parole_media_list_open_internal (ParoleMediaList *list)
 {
     GtkWidget *chooser;
     
-    chooser = parole_media_chooser_open_local (gtk_widget_get_toplevel (GTK_WIDGET (list)), 
-					       multiple);
+    chooser = parole_media_chooser_open_local (gtk_widget_get_toplevel (GTK_WIDGET (list)));
 					       
-    if ( multiple )
-	g_signal_connect (G_OBJECT (chooser), "media_files_opened",
-		          G_CALLBACK (parole_media_list_files_opened_cb), list);
-    else
-	g_signal_connect (G_OBJECT (chooser), "media_file_opened",
-		          G_CALLBACK (parole_media_list_file_opened_cb), list);
+    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));
 }
@@ -223,7 +270,7 @@
 {
     GSList *file_list = NULL;
     GtkFileFilter *filter;
-    ParoleMediaFile *file;
+    ParoleFile *file;
     guint len;
     gboolean ret = FALSE;
     
@@ -244,6 +291,28 @@
     return ret;
 }
 
+static GSList *
+parole_media_list_get_files (ParoleMediaList *list)
+{
+    ParoleFile *file;
+    GtkTreeIter iter;
+    gboolean valid;
+    GSList *files_list = NULL;
+    
+    for ( valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (list->priv->store), &iter);
+	  valid;
+	  valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (list->priv->store), &iter))
+    {
+	gtk_tree_model_get (GTK_TREE_MODEL (list->priv->store), &iter,
+			    DATA_COL, &file,
+			    -1);
+	
+	files_list = g_slist_append (files_list, file);
+    }
+    
+    return files_list;
+}
+
 void	parole_media_list_drag_data_received_cb (GtkWidget *widget,
 						 GdkDragContext *drag_context,
 						 gint x,
@@ -280,14 +349,162 @@
 void
 parole_media_list_add_clicked_cb (GtkButton *button, ParoleMediaList *list)
 {
-    parole_media_list_open_internal (list, TRUE);
+    parole_media_list_open_internal (list);
 }
 
+void parole_media_list_close_save_dialog_cb (GtkButton *button, ParolePlaylistSave *data)
+{
+    gtk_widget_destroy (GTK_WIDGET (data->chooser));
+    g_free (data);
+}
+						    
+void parole_media_list_save_playlist_cb (GtkButton *button, ParolePlaylistSave *data)
+{
+    ParolePlFormat format = PAROLE_PL_FORMAT_UNKNOWN;
+    GSList *list = NULL;
+    GtkTreeModel *model;
+    GtkTreeIter iter;
+    gchar *filename;
+    gchar *dirname;
+    
+    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (data->chooser));
+    dirname = g_path_get_dirname (filename);
+    
+    if ( gtk_tree_selection_get_selected (data->sel, &model, &iter ) )
+    {
+	gtk_tree_model_get (model, &iter, 2, &format, -1);
+    }
+    
+    if ( g_access (dirname, W_OK) == -1 )
+    {
+	xfce_err ("%s %s %s", _("Error saving playlist file"), dirname, _("Permission denied"));
+	goto out;
+    }
+    
+    if ( format == PAROLE_PL_FORMAT_UNKNOWN )
+    {
+	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"));
+	    goto out;
+	}
+    }
+    
+    list = parole_media_list_get_files (data->list);
+    
+    parole_media_list_close_save_dialog_cb (NULL, data);
+    
+    parole_pl_parser_save_file (list, filename, format);
+    g_slist_free (list);
+out:
+    g_free (filename);
+    g_free (dirname);
+}
+
+void parole_media_list_format_cursor_changed_cb (GtkTreeView *view, ParolePlaylistSave *data)
+{
+    GtkTreeIter iter;
+    GtkTreeModel *model;
+    ParolePlFormat format;
+    gchar *filename;
+    gchar *fbasename;
+    
+    filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (data->chooser));
+    fbasename = g_path_get_basename (filename);
+    
+    g_free (filename);
+    
+    if ( gtk_tree_selection_get_selected (data->sel, &model, &iter ) )
+    {
+	gtk_tree_model_get (model, &iter, 2, &format, -1);
+	if ( format != PAROLE_PL_FORMAT_UNKNOWN )
+	{
+	    gchar *name, *new_name;
+	    name = parole_get_name_without_extension (fbasename);
+	    new_name = g_strdup_printf ("%s%s", name, playlist_format_map[format].ext);
+	    gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (data->chooser), new_name);
+	    g_free (new_name);
+	    g_free (name);
+	}
+    }
+    g_free (fbasename);
+    
+}
+
+void parole_media_list_save_cb (GtkButton *button, ParoleMediaList *list)
+{
+    ParolePlaylistSave *data;
+    GtkWidget *chooser;
+    GtkWidget *view;
+    GtkListStore *store;
+    GtkBuilder *builder;
+    gchar *filename;
+    GtkTreeIter iter;
+    
+    data = g_new0 (ParolePlaylistSave, 1);
+    
+    builder = parole_builder_new_from_string (save_playlist_ui, save_playlist_ui_length);
+    
+    chooser = GTK_WIDGET (gtk_builder_get_object (builder, "filechooserdialog"));
+    store = GTK_LIST_STORE (gtk_builder_get_object (builder, "liststore"));
+
+    gtk_window_set_transient_for (GTK_WINDOW (chooser), 
+				  GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (list))));
+	
+    filename = g_strconcat (_("Playlist"), ".m3u", NULL);
+    gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (chooser), filename);
+    g_free (filename);
+    
+    gtk_list_store_append (store, &iter);
+    gtk_list_store_set (store, 
+			&iter, 
+			0, _("M3U Playlists"),
+			1, "m3u",
+			2, PAROLE_PL_FORMAT_M3U,
+			-1);
+			
+    gtk_list_store_append (store, &iter);
+    gtk_list_store_set (store, 
+			&iter, 
+			0, _("PLS Playlists"),
+			1, "pls",
+			2, PAROLE_PL_FORMAT_PLS,
+			-1);
+			
+    gtk_list_store_append (store, &iter);
+    gtk_list_store_set (store, 
+			&iter, 
+			0, _("Advanced Stream Redirector"),
+			1, "asx",
+			2, PAROLE_PL_FORMAT_ASX,
+			-1);
+			
+    gtk_list_store_append (store, &iter);
+    gtk_list_store_set (store, 
+			&iter, 
+			0, _("Shareable Playlist"),
+			1, "xspf",
+			2, PAROLE_PL_FORMAT_XSPF,
+			-1);
+
+    view = GTK_WIDGET (gtk_builder_get_object (builder, "treeview"));
+    
+    data->chooser = chooser;
+    data->sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+    data->list = list;
+
+    gtk_builder_connect_signals (builder, data);
+    gtk_widget_show_all (chooser);
+    g_object_unref (builder);
+}
+
 void
 parole_media_list_remove_clicked_cb (GtkButton *button, ParoleMediaList *list)
 {
     GtkTreeSelection *sel;
     GtkTreeIter iter;
+    gint nch;
     
     sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (list->priv->view));
     
@@ -302,12 +519,21 @@
      * As a special case, if iter is NULL, 
      * then the number of toplevel nodes is returned. Gtk API doc.
      */
-    if ( gtk_tree_model_iter_n_children (GTK_TREE_MODEL (list->priv->store), NULL) == 0 )
+    nch = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (list->priv->store), NULL); 
+    if ( nch == 0)
+    {
+	parole_media_list_set_widget_sensitive (list, FALSE);
 	/*
 	 * Will emit the signal media_cursor_changed with FALSE because there is no any 
-	 * row remaining so the player can disable click on the play button.
+	 * row remaining, so the player can disable click on the play button.
 	 */
 	g_signal_emit (G_OBJECT (list), signals [MEDIA_CURSOR_CHANGED], 0, FALSE);
+    }
+    else if ( nch == 1 )
+    {
+	gtk_widget_set_sensitive (list->priv->up, FALSE);
+	gtk_widget_set_sensitive (list->priv->down, FALSE);
+    }
 }
 
 void
@@ -414,15 +640,17 @@
 parole_media_list_clear_list (ParoleMediaList *list)
 {
     gtk_list_store_clear (GTK_LIST_STORE (list->priv->store));
+    parole_media_list_set_widget_sensitive (list, FALSE);
 }
 
 static void
 parole_media_list_show_menu (ParoleMediaList *list, guint button, guint activate_time)
 {
     GtkWidget *menu, *mi;
-    
+
     menu = gtk_menu_new ();
     
+    /* Clear */
     mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL);
     gtk_widget_set_sensitive (mi, TRUE);
     gtk_widget_show (mi);
@@ -556,6 +784,11 @@
 
     gtk_box_pack_start (GTK_BOX (list), box, TRUE, TRUE, 0);
 
+    list->priv->up = GTK_WIDGET (gtk_builder_get_object (builder, "media-up"));
+    list->priv->down = GTK_WIDGET (gtk_builder_get_object (builder, "media-down"));
+    list->priv->remove = GTK_WIDGET (gtk_builder_get_object (builder, "remove-media"));
+    list->priv->save = GTK_WIDGET (gtk_builder_get_object (builder, "save-playlist"));
+
     g_object_unref (builder);
     
     gtk_widget_show_all (GTK_WIDGET (list));
@@ -667,9 +900,9 @@
     }
 }
 
-void parole_media_list_open (ParoleMediaList *list, gboolean multiple)
+void parole_media_list_open (ParoleMediaList *list)
 {
-    parole_media_list_open_internal (list, multiple);
+    parole_media_list_open_internal (list);
 }
 
 void parole_media_list_open_location (ParoleMediaList *list)

Modified: parole/trunk/parole/parole-medialist.h
===================================================================
--- parole/trunk/parole/parole-medialist.h	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-medialist.h	2009-07-23 21:35:01 UTC (rev 7778)
@@ -80,8 +80,7 @@
 							             GtkTreeRowReference *row,
 								     const gchar *name);
 
-void				 parole_media_list_open		    (ParoleMediaList *list,
-								     gboolean multiple);
+void				 parole_media_list_open		    (ParoleMediaList *list);
 
 void			         parole_media_list_open_location    (ParoleMediaList *list);
 

Added: parole/trunk/parole/parole-pl-parser.c
===================================================================
--- parole/trunk/parole/parole-pl-parser.c	                        (rev 0)
+++ parole/trunk/parole/parole-pl-parser.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -0,0 +1,660 @@
+/*
+ * * 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
+ */
+
+/*
+ * Based on code from:
+ * 
+ * Totem pl parser:	Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Bastien Nocera
+ * 		        Copyright (C) 2003, 2004 Colin Walters <walters at rhythmbox.org>
+ * 
+ * xfmedia:		Copyright (c) 2004-2005 Brian Tarricone, <bjt23 at cornell.edu>
+ * 
+ * Thanks :).
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gio/gio.h>
+#include <libxfce4util/libxfce4util.h>
+
+#include "parole-pl-parser.h"
+#include "parole-file.h"
+#include "parole-filters.h"
+#include "parole-debug.h"
+#include "enum-gtypes.h"
+
+typedef struct
+{
+    GSList    *list;
+    gboolean  started;
+    gchar    *uri;
+    gchar    *title;
+    
+} ParoleParserData;
+
+static void
+parole_xspf_xml_start (GMarkupParseContext *context, const gchar *element_name,
+		       const gchar **attribute_names, const gchar **attribute_values,
+		       gpointer user_data, GError **error)
+{
+    ParoleParserData *data = user_data;
+    
+    if ( !data->started )
+    {
+	if (!g_ascii_strcasecmp (element_name, "playlist") )
+	    data->started = TRUE;
+    }
+}
+
+static void
+parole_xspf_xml_text (GMarkupParseContext *context, const gchar *text, gsize text_len,  
+		      gpointer user_data, GError **error)
+{
+    ParoleParserData *data = user_data;
+    const gchar *element_name;
+    
+    if (!data->started)
+        return;
+    
+    element_name = g_markup_parse_context_get_element (context);
+    
+    if (!g_ascii_strcasecmp (element_name, "location") ) 
+    {
+        if (data->uri) 
+	{
+            g_free (data->uri);
+            data->uri = NULL;
+        }
+	
+        if (text_len > 0)
+            data->uri = g_strdup (text);
+    }
+    else if (!g_ascii_strcasecmp (element_name, "title") ) 
+    {
+        if (data->title) 
+	{
+            g_free (data->title);
+            data->title = NULL;
+        }
+	
+        if (text_len > 0)
+            data->title = g_strdup (text);
+    }
+}
+
+static void
+parole_xspf_xml_end (GMarkupParseContext *context, const gchar *element_name,
+		     gpointer user_data, GError **error)
+{
+    ParoleParserData *data = user_data;
+    ParoleFile *file;
+    
+    if (! g_ascii_strcasecmp (element_name, "playlist"))
+        data->started = FALSE;
+	
+    if (!data->started)
+        return;
+	
+    if (!g_ascii_strcasecmp (element_name, "track")) 
+    {
+        if (data->uri) 
+	{
+	    file = parole_file_new_with_display_name (data->uri, data->title);
+	    data->list = g_slist_append (data->list, file);
+	    
+	    g_free (data->uri);
+	    data->uri = NULL;
+	}
+	
+	if ( data->title)
+	{
+	    g_free (data->title);
+	    data->title = NULL;
+	}
+    }
+}
+
+static void
+parole_asx_xml_start (GMarkupParseContext *context, const gchar *element_name,
+		      const gchar **attribute_names, const gchar **attribute_values,
+		      gpointer user_data, GError **error)
+{
+    guint i;
+    ParoleParserData *data = user_data;
+    
+    if ( !data->started )
+    {
+	if (!g_ascii_strcasecmp (element_name, "asx") )
+	    data->started = TRUE;
+	else
+	    return;
+    }
+    
+    if (!g_ascii_strcasecmp (element_name, "ref") ) 
+    {
+        if (data->uri) 
+	{
+            g_free (data->uri);
+            data->uri = NULL;
+        }
+	
+        for ( i = 0; attribute_names[i]; i++) 
+	{
+            if ( !g_ascii_strcasecmp (attribute_names[i], "href")) 
+	    {
+                data->uri = g_strdup (attribute_values[i]);
+                break;
+            }
+        }
+    }
+}
+
+static void
+parole_asx_xml_text (GMarkupParseContext *context, const gchar *text, gsize text_len,  
+		     gpointer user_data, GError **error)
+{
+    ParoleParserData *data = user_data;
+    const gchar *element_name;
+    
+    if (!data->started)
+        return;
+    
+    element_name = g_markup_parse_context_get_element (context);
+    
+    if (!g_ascii_strcasecmp (element_name, "title") ) 
+    {
+        if (data->title) 
+	{
+            g_free (data->title);
+            data->title = NULL;
+        }
+	
+        if (text_len > 0)
+            data->title = g_strdup (text);
+    }
+}
+
+static void
+parole_asx_xml_end (GMarkupParseContext *context, const gchar *element_name,
+		    gpointer user_data, GError **error)
+{
+    ParoleParserData *data = user_data;
+    ParoleFile *file;
+    
+    if (!g_ascii_strcasecmp (element_name, "ASX"))
+        data->started = FALSE;
+	
+    if (!data->started)
+        return;
+	
+    if (!g_ascii_strcasecmp (element_name, "entry")) 
+    {
+        if (data->uri) 
+	{
+	    file = parole_file_new_with_display_name (data->uri, data->title);
+	    data->list = g_slist_append (data->list, file);
+	    
+	    g_free (data->uri);
+	    data->uri = NULL;
+	}
+	
+	if ( data->title)
+	{
+	    g_free (data->title);
+	    data->title = NULL;
+	}
+    }
+}
+
+ParolePlFormat
+parole_pl_parser_guess_format_from_extension (const gchar *filename)
+{
+    if ( g_str_has_suffix (filename, ".m3u") || g_str_has_suffix (filename, ".M3U") )
+	return PAROLE_PL_FORMAT_M3U;
+	
+    if ( g_str_has_suffix (filename, ".pls") || g_str_has_suffix (filename, ".PLS") )
+	return PAROLE_PL_FORMAT_PLS;
+	
+    if ( g_str_has_suffix (filename, ".xspf") || g_str_has_suffix (filename, ".XSPF") )
+	return PAROLE_PL_FORMAT_XSPF;
+	
+    if ( g_str_has_suffix (filename, ".asx") || g_str_has_suffix (filename, ".ASX") )
+	return PAROLE_PL_FORMAT_ASX;
+	
+    if ( g_str_has_suffix (filename, ".wax") || g_str_has_suffix (filename, ".WAX") )
+	return PAROLE_PL_FORMAT_XSPF;
+	
+    return PAROLE_PL_FORMAT_UNKNOWN;
+}
+
+static ParolePlFormat
+parole_pl_parser_guess_format_from_data (const gchar *filename)
+{
+    
+    return PAROLE_PL_FORMAT_UNKNOWN;
+}
+
+static GSList *
+parole_pl_parser_parse_asx (const gchar *filename)
+{
+    ParoleParserData data;
+    GFile *file;
+    gchar *contents;
+    GError *error = NULL;
+    gsize size;
+    GMarkupParseContext *pctx;
+    GMarkupParser parser = {
+        parole_asx_xml_start,
+        parole_asx_xml_end,
+        parole_asx_xml_text,
+        NULL,
+        NULL
+    };
+    
+    data.list = NULL;
+    data.title = data.uri = NULL;
+    
+    file = g_file_new_for_path (filename);
+    
+    if ( !g_file_load_contents (file, NULL, &contents, &size, NULL, NULL) )
+	goto out;
+    
+    if ( g_utf8_validate (contents, -1, NULL) == FALSE) 
+    {
+	gchar *fixed;
+	fixed = g_convert (contents, -1, "UTF-8", "ISO8859-1", NULL, NULL, NULL);
+	if (fixed != NULL) 
+	{
+	    g_free (contents);
+	    contents = fixed;
+	}
+    }
+    
+    pctx = g_markup_parse_context_new (&parser, 0, &data, NULL);
+    
+    if ( !g_markup_parse_context_parse (pctx, contents, size, &error) )
+    {
+	if ( error )
+	{
+	    g_critical ("Unable to parse asx file : %s : %s\n", filename, error->message);
+	    g_error_free (error);
+	}
+    }
+    else
+    {
+	if ( !g_markup_parse_context_end_parse (pctx, &error) )
+	{
+            g_critical ("Unable to finish parsing ASX playlist file %s", error->message);
+            g_error_free (error);
+        }
+    }
+    
+    g_markup_parse_context_free (pctx);
+    
+out:
+    g_object_unref (file);
+    return data.list;
+}
+
+static GSList *
+parole_pl_parser_parse_m3u (const gchar *filename)
+{
+    GFile *file;
+    gchar **lines;
+    gchar *contents;
+    GSList *list = NULL;
+    gsize size;
+    guint num_lines;
+    const gchar *split_char;
+    guint i;
+    
+    file = g_file_new_for_path (filename);
+    
+    if ( !g_file_load_contents (file, NULL, &contents, &size, NULL, NULL) )
+	goto out;
+    
+    if ( g_utf8_validate (contents, -1, NULL) == FALSE) 
+    {
+	gchar *fixed;
+	fixed = g_convert (contents, -1, "UTF-8", "ISO8859-1", NULL, NULL, NULL);
+	if (fixed != NULL) 
+	{
+	    g_free (contents);
+	    contents = fixed;
+	}
+    }
+    
+    if ( strstr (contents,"\x0d") == NULL) 
+    {
+	split_char = "\n";
+    } 
+    else 
+    {
+	split_char = "\x0d\n";
+    }
+    
+    lines = g_strsplit (contents, split_char, 0);
+    g_free (contents);
+    
+    num_lines = g_strv_length (lines);
+    num_lines--; /* Drop the terminating NULL */
+
+    for ( i = 0; lines[i] != NULL; i++)
+    {
+	if ( lines[i][0] == '\0' || lines[i][0] == '#')
+	    continue;
+
+	list = g_slist_append (list, parole_file_new (lines[i]));
+    }
+
+    g_strfreev (lines);
+out:
+
+    g_object_unref (file);
+
+    return list;
+}
+
+static GSList *
+parole_pl_parser_parse_pls (const gchar *filename)
+{
+    XfceRc *rcfile;
+    GSList *list = NULL;
+    ParoleFile *file;
+    const gchar *file_entry, *title_entry;
+    guint i, nentries;
+    gchar key[128];
+
+    rcfile = xfce_rc_simple_open (filename, TRUE);
+
+    if ( xfce_rc_has_group (rcfile, "playlist") ) 
+    {
+        xfce_rc_set_group (rcfile, "playlist");
+        
+        nentries = xfce_rc_read_int_entry (rcfile, "NumberOfEntries", 0);
+
+        for (i = 1; i <= nentries; i++) 
+	{
+            g_snprintf (key, 128, "File%d", i);
+	    
+            file_entry = xfce_rc_read_entry (rcfile, key, NULL);
+	    
+            if (!file_entry)
+                continue;
+	    
+	    g_snprintf (key, 128, "Title%d", i);
+	    
+            title_entry = xfce_rc_read_entry (rcfile, key, NULL);
+	    
+	    file = parole_file_new_with_display_name (file_entry, title_entry);
+	    list = g_slist_append (list, file);
+	}
+    }
+    
+    xfce_rc_close (rcfile);
+    
+    return list;
+}
+
+static GSList *
+parole_pl_parser_parse_xspf (const gchar *filename)
+{
+    GSList *list = NULL;
+    
+    ParoleParserData data;
+    GFile *file;
+    gchar *contents;
+    GError *error = NULL;
+    gsize size;
+    GMarkupParseContext *pctx;
+    GMarkupParser parser = {
+        parole_xspf_xml_start,
+        parole_xspf_xml_end,
+        parole_xspf_xml_text,
+        NULL,
+        NULL
+    };
+    
+    data.list = NULL;
+    data.title = data.uri = NULL;
+    
+    file = g_file_new_for_path (filename);
+    
+    if ( !g_file_load_contents (file, NULL, &contents, &size, NULL, NULL) )
+	goto out;
+    
+    if ( g_utf8_validate (contents, -1, NULL) == FALSE) 
+    {
+	gchar *fixed;
+	fixed = g_convert (contents, -1, "UTF-8", "ISO8859-1", NULL, NULL, NULL);
+	if (fixed != NULL) 
+	{
+	    g_free (contents);
+	    contents = fixed;
+	}
+    }
+    
+    pctx = g_markup_parse_context_new (&parser, 0, &data, NULL);
+    
+    if ( !g_markup_parse_context_parse (pctx, contents, size, &error) )
+    {
+	if ( error )
+	{
+	    g_critical ("Unable to parse xspf file : %s : %s\n", filename, error->message);
+	    g_error_free (error);
+	}
+    }
+    else
+    {
+	if ( !g_markup_parse_context_end_parse (pctx, &error) )
+	{
+            g_critical ("Unable to finish parsing xspf playlist file %s", error->message);
+            g_error_free (error);
+        }
+    }
+    
+    g_markup_parse_context_free (pctx);
+    
+out:
+    g_object_unref (file);
+    return data.list;
+    
+    return list;
+}
+
+static GSList *
+parole_pl_parser_parse (ParolePlFormat format, const gchar *filename)
+{
+    GSList *list = NULL;
+    
+    switch (format)
+    {
+	case PAROLE_PL_FORMAT_M3U:
+	    list = parole_pl_parser_parse_m3u (filename);
+	    break;
+	case PAROLE_PL_FORMAT_PLS:
+	    list = parole_pl_parser_parse_pls (filename);
+	    break;
+	case PAROLE_PL_FORMAT_ASX:
+	    list = parole_pl_parser_parse_asx (filename);
+	    break;
+	case PAROLE_PL_FORMAT_XSPF:
+	    list = parole_pl_parser_parse_xspf (filename);
+	    break;
+	default:
+	    break;
+    }
+
+    return list;
+}
+
+GSList *parole_pl_parser_load_file (const gchar *filename)
+{
+    ParolePlFormat format = PAROLE_PL_FORMAT_UNKNOWN;
+    GtkFileFilter *filter;
+    GSList *list = NULL;
+    
+    filter = parole_get_supported_playlist_filter ();
+    g_object_ref_sink (filter);
+    
+    if ( (format = parole_pl_parser_guess_format_from_extension (filename)) == PAROLE_PL_FORMAT_UNKNOWN)
+	if ( (format = parole_pl_parser_guess_format_from_data (filename)) == PAROLE_PL_FORMAT_UNKNOWN)
+	{
+	    g_debug ("Unable to guess playlist format of file : %s", filename);
+	    goto out;
+	}
+	    
+    PAROLE_DEBUG_ENUM_FULL (format, ENUM_GTYPE_PL_FORMAT, "playlist %s ", filename);
+    list = parole_pl_parser_parse (format, filename);
+	
+out:
+    g_object_unref (filter);
+    
+    return list;
+}
+
+static gboolean
+parole_pl_parser_save_m3u (FILE *f, GSList *files)
+{
+    guint len;
+    guint i;
+    
+    fputs ("#EXTM3U\n", f);
+    
+    len = g_slist_length (files);
+    
+    for ( i = 0; i < len; i++)
+    {
+	ParoleFile *file;
+	file = g_slist_nth_data (files, i);
+	fprintf (f, "%s\n", parole_file_get_file_name (file));
+    }
+    
+    return TRUE;
+}
+
+static gboolean
+parole_pl_parser_save_pls (FILE *f, GSList *files)
+{
+    guint len;
+    guint i;
+    gchar key[128];
+    
+    len = g_slist_length (files);
+    
+    fprintf (f, "[playlist]\nNumberOfEntries=%d\n", len);
+    
+    for ( i = 1; i <= len; i++)
+    {
+	ParoleFile *file;
+	file = g_slist_nth_data (files, i - 1);
+	g_snprintf (key, 128, "File%d", i);
+	fprintf (f, "%s=%s\n", key, parole_file_get_file_name (file));
+    }
+    
+    return TRUE;
+}
+
+static gboolean
+parole_pl_parser_save_asx (FILE *f, GSList *files)
+{
+    guint len;
+    guint i;
+    
+    len = g_slist_length (files);
+
+    fputs ("<ASX VERSION=\"3.0\">\n", f);
+    
+    for ( i = 0; i < len; i++)
+    {
+	ParoleFile *file;
+	file = g_slist_nth_data (files, i);
+	fprintf (f, "  <ENTRY>\n   <TITLE>%s</TITLE>\n    <REF HREF=\"%s\"/>\n  </ENTRY>\n", 
+		 parole_file_get_display_name (file),
+		 parole_file_get_uri (file));
+    }
+    
+    fputs ("</ASX>\n", f);
+    
+    return TRUE;
+}
+
+static gboolean
+parole_pl_parser_save_xspf (FILE *f, GSList *files)
+{
+    guint len;
+    guint i;
+    
+    len = g_slist_length (files);
+    
+    fputs ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+	   "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\n", f);
+	   
+    fputs (" <trackList>\n", f);
+    
+    for ( i = 0; i < len; i++)
+    {
+	ParoleFile *file;
+	file = g_slist_nth_data (files, i);
+	fprintf (f, "  <track>\n    <location>%s</location>\n  </track>\n", parole_file_get_uri (file));
+    }
+    
+    fputs (" </trackList>\n<playlist>", f);
+    
+    return TRUE;
+}
+
+gboolean parole_pl_parser_save_file (GSList *files, const gchar *filename, ParolePlFormat format)
+{
+    FILE *f;
+    gboolean ret_val;
+
+    PAROLE_DEBUG_ENUM_FULL (format, ENUM_GTYPE_PL_FORMAT, "Saving playlist %s ", filename);
+    
+    f = fopen (filename, "w");
+    
+    switch (format)
+    {
+	case PAROLE_PL_FORMAT_M3U:
+	    ret_val = parole_pl_parser_save_m3u (f, files);
+	    break;
+	case PAROLE_PL_FORMAT_PLS:
+	    ret_val = parole_pl_parser_save_pls (f, files);
+	    break;
+	case PAROLE_PL_FORMAT_ASX:
+	    ret_val = parole_pl_parser_save_asx (f, files);
+	    break;
+	case PAROLE_PL_FORMAT_XSPF:
+	    ret_val = parole_pl_parser_save_xspf (f, files);
+	    break;
+	default:
+	    break;
+    }
+    
+    fclose (f);
+    
+    return ret_val;
+}

Added: parole/trunk/parole/parole-pl-parser.h
===================================================================
--- parole/trunk/parole/parole-pl-parser.h	                        (rev 0)
+++ parole/trunk/parole/parole-pl-parser.h	2009-07-23 21:35:01 UTC (rev 7778)
@@ -0,0 +1,48 @@
+/*
+ * * 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_PL_PARSER_H
+#define __PAROLE_PL_PARSER_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+    PAROLE_PL_FORMAT_UNKNOWN,
+    PAROLE_PL_FORMAT_M3U,
+    PAROLE_PL_FORMAT_PLS,
+    PAROLE_PL_FORMAT_ASX,
+    PAROLE_PL_FORMAT_XSPF
+    
+} ParolePlFormat;
+
+ParolePlFormat		 parole_pl_parser_guess_format_from_extension   (const gchar *filename);
+
+GSList 			*parole_pl_parser_load_file		        (const gchar *filename);
+
+gboolean		 parole_pl_parser_save_file		        (GSList *files,
+								         const gchar *filename,
+									 ParolePlFormat format);
+
+G_END_DECLS
+
+#endif /* __PAROLE_PL_PARSER_H */

Modified: parole/trunk/parole/parole-player.c
===================================================================
--- parole/trunk/parole/parole-player.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-player.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -32,14 +32,13 @@
 #include <libxfce4util/libxfce4util.h>
 #include <libxfcegui4/libxfcegui4.h>
 
-#include "common/parole-builder.h"
-#include "common/parole-about.h"
+#include "parole-builder.h"
+#include "parole-about.h"
 
 #include "parole-player.h"
-#include "parole-sidebar.h"
 #include "parole-gst.h"
 #include "parole-mediachooser.h"
-#include "parole-mediafile.h"
+#include "parole-file.h"
 #include "parole-disc.h"
 #include "parole-statusbar.h"
 #include "parole-screensaver.h"
@@ -81,9 +80,6 @@
 							 ParolePlayer *player);
 
 /*Menu items callbacks*/
-void            parole_player_menu_open_cb              (GtkWidget *widget, 
-							 ParolePlayer *player);
-
 void            parole_player_menu_open_location_cb     (GtkWidget *widget, 
 							 ParolePlayer *player);
 
@@ -122,7 +118,6 @@
     ParoleStatusbar     *status;
     ParoleDisc          *disc;
     ParoleScreenSaver   *screen_saver;
-    ParoleSidebar       *sidebar;
 
     GtkWidget 		*gst;
 
@@ -214,7 +209,7 @@
 static void
 parole_player_media_activated_cb (ParoleMediaList *list, GtkTreeRowReference *row, ParolePlayer *player)
 {
-    ParoleMediaFile *file;
+    ParoleFile *file;
     GtkTreeIter iter;
     GtkTreeModel *model;
 
@@ -229,9 +224,9 @@
 	
 	if ( file )
 	{
-	    TRACE ("Trying to play media file %s", parole_media_file_get_uri (file));
+	    TRACE ("Trying to play media file %s", parole_file_get_uri (file));
 	    gtk_widget_set_sensitive (player->priv->stop, TRUE);
-	    parole_gst_play_uri (PAROLE_GST (player->priv->gst), parole_media_file_get_uri (file));
+	    parole_gst_play_uri (PAROLE_GST (player->priv->gst), parole_file_get_uri (file));
 	    g_object_unref (file);
 	}
     }
@@ -624,7 +619,6 @@
 {
     if ( player->priv->full_screen )
     {
-	parole_sidebar_set_visible (player->priv->sidebar, TRUE); 
 	parole_statusbar_set_visible (player->priv->status, TRUE);
 	gtk_widget_show (player->priv->play_box);
 	gtk_widget_show (player->priv->menu_bar);
@@ -634,7 +628,6 @@
     }
     else
     {
-	parole_sidebar_set_visible (player->priv->sidebar, FALSE); 
 	parole_statusbar_set_visible (player->priv->status, FALSE);
 	gtk_widget_hide (player->priv->play_box);
 	gtk_widget_hide (player->priv->menu_bar);
@@ -756,12 +749,6 @@
 }
 
 void
-parole_player_menu_open_cb (GtkWidget *widget, ParolePlayer *player)
-{
-    parole_media_list_open (player->priv->list, FALSE);
-}
-
-void
 parole_player_menu_open_location_cb (GtkWidget *widget, ParolePlayer *player)
 {
     parole_media_list_open_location (player->priv->list);
@@ -770,7 +757,7 @@
 void
 parole_player_menu_add_cb (GtkWidget *widget, ParolePlayer *player)
 {
-    parole_media_list_open (player->priv->list, TRUE);
+    parole_media_list_open (player->priv->list);
 }
 
 void parole_player_open_preferences_cb	(GtkWidget *widget, ParolePlayer *player)
@@ -846,7 +833,6 @@
     g_object_unref (player->priv->status);
     g_object_unref (player->priv->disc);
     g_object_unref (player->priv->screen_saver);
-    g_object_unref (player->priv->sidebar);
 
     G_OBJECT_CLASS (parole_player_parent_class)->finalize (object);
 }
@@ -890,7 +876,6 @@
      */
     g_object_ref (player->priv->gst);
     
-    player->priv->sidebar = parole_sidebar_new ();
     player->priv->status = parole_statusbar_new ();
     player->priv->disc = parole_disc_new ();
     g_signal_connect (player->priv->disc, "disc-selected",

Modified: parole/trunk/parole/parole-plugin.c
===================================================================
--- parole/trunk/parole/parole-plugin.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-plugin.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -27,7 +27,6 @@
 #include <string.h>
 
 #include "parole-plugin.h"
-#include "parole-medialist.h"
 #include "parole-plugins-manager.h"
 #include "parole-gst.h"
 #include "gmarshal.h"
@@ -392,23 +391,6 @@
 }
 
 /**
- * parole_plugin_play_file:
- * @plugin: a #ParolePlugin.
- * @file: a #ParoleMefiaFile to play.
- * 
- * Play a #ParoleMediaFile.
- * 
- * Returns: TRUE on success, FALSE otherwise.
- **/
-gboolean parole_plugin_play_file (ParolePlugin *plugin, ParoleMediaFile *file)
-{
-    
-    
-    
-    return TRUE;
-}
-
-/**
  * parole_plugin_pause_playing:
  * @plugin: a #ParolePlugin.
  * 

Modified: parole/trunk/parole/parole-plugin.h
===================================================================
--- parole/trunk/parole/parole-plugin.h	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-plugin.h	2009-07-23 21:35:01 UTC (rev 7778)
@@ -25,7 +25,6 @@
 #include <gtk/gtk.h>
 
 #include <parole/parole-stream.h>
-#include <parole/parole-mediafile.h>
 
 G_BEGIN_DECLS
 
@@ -87,9 +86,6 @@
 gboolean		     parole_plugin_play_uri        (ParolePlugin *plugin,
 							    const gchar *uri);
 
-gboolean		     parole_plugin_play_file       (ParolePlugin *plugin,
-							    ParoleMediaFile *file);
-							    
 gboolean		     parole_plugin_pause_playing   (ParolePlugin *plugin);
 
 gboolean		     parole_plugin_resume          (ParolePlugin *plugin);

Modified: parole/trunk/parole/parole-plugins-manager.c
===================================================================
--- parole/trunk/parole/parole-plugins-manager.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-plugins-manager.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -30,8 +30,7 @@
 
 #include <libxfce4util/libxfce4util.h>
 
-#include "common/parole-builder.h"
-
+#include "parole-builder.h"
 #include "parole-plugins-manager.h"
 #include "parole-module.h"
 

Modified: parole/trunk/parole/parole-statusbar.c
===================================================================
--- parole/trunk/parole/parole-statusbar.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-statusbar.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -30,8 +30,7 @@
 
 #include <libxfcegui4/libxfcegui4.h>
 
-#include "common/parole-builder.h"
-
+#include "parole-builder.h"
 #include "parole-statusbar.h"
 
 #define PAROLE_STATUSBAR_GET_PRIVATE(o) \

Modified: parole/trunk/parole/parole-stream.c
===================================================================
--- parole/trunk/parole/parole-stream.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-stream.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -29,7 +29,7 @@
 #include <glib.h>
 
 #include "parole-stream.h"
-#include "parole-mediafile.h"
+#include "parole-file.h"
 
 #define PAROLE_STREAM_GET_PRIVATE(o) \
 (G_TYPE_INSTANCE_GET_PRIVATE ((o), PAROLE_TYPE_STREAM, ParoleStreamPrivate))

Modified: parole/trunk/parole/parole-utils.c
===================================================================
--- parole/trunk/parole/parole-utils.c	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-utils.c	2009-07-23 21:35:01 UTC (rev 7778)
@@ -125,8 +125,8 @@
  * 
  */
 gint
-thunar_file_compare_by_name (ParoleMediaFile *file_a,
-                             ParoleMediaFile *file_b,
+thunar_file_compare_by_name (ParoleFile *file_a,
+                             ParoleFile *file_b,
                              gboolean         case_sensitive)
 {
     const gchar *ap;
@@ -136,8 +136,8 @@
 
 
     /* we compare only the display names (UTF-8!) */
-    ap = parole_media_file_get_display_name (file_a);
-    bp = parole_media_file_get_display_name (file_b);
+    ap = parole_file_get_display_name (file_a);
+    bp = parole_file_get_display_name (file_b);
 
     /* check if we should ignore case */
     if (G_LIKELY (case_sensitive))
@@ -207,7 +207,7 @@
 	/* a second case is '20 file' and '2file', where comparison by number
 	 * makes sense, if the previous char for both strings is a digit.
 	 */
-	if (ap > parole_media_file_get_display_name (file_a) && bp > parole_media_file_get_display_name (file_b)
+	if (ap > parole_file_get_display_name (file_a) && bp > parole_file_get_display_name (file_b)
 	    && g_ascii_isdigit (*(ap - 1)) && g_ascii_isdigit (*(bp - 1)))
         {
 	    return compare_by_name_using_number (ap - 1, bp - 1);

Modified: parole/trunk/parole/parole-utils.h
===================================================================
--- parole/trunk/parole/parole-utils.h	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/parole/parole-utils.h	2009-07-23 21:35:01 UTC (rev 7778)
@@ -24,14 +24,14 @@
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 
-#include "parole-mediafile.h"
+#include "parole-file.h"
 
 void		parole_window_busy_cursor		(GdkWindow *window);
 
 void		parole_window_invisible_cursor		(GdkWindow *window);
 
-gint            thunar_file_compare_by_name 		(ParoleMediaFile *file_a,
-							 ParoleMediaFile *file_b,
+gint            thunar_file_compare_by_name 		(ParoleFile *file_a,
+							 ParoleFile *file_b,
 							 gboolean         case_sensitive);
 
 gchar          *parole_get_name_without_extension 	(const gchar *name)G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;

Modified: parole/trunk/po/POTFILES.in
===================================================================
--- parole/trunk/po/POTFILES.in	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/po/POTFILES.in	2009-07-23 21:35:01 UTC (rev 7778)
@@ -4,13 +4,16 @@
 [type: gettext/glade]data/interfaces/playlist.ui
 [type: gettext/glade]data/interfaces/openlocation.ui
 [type: gettext/glade]data/interfaces/parole-settings.ui
+[type: gettext/glade]data/interfaces/save-playlist.ui
 data/desktop/parole.desktop.in.in
 parole/main.c
 parole/parole-gst.c
 parole/parole-mediachooser.c
 parole/parole-medialist.c
 parole/parole-player.c
-parole/parole-sidebar.c
 parole/parole-statusbar.c
 parole/parole-filters.c
+parole/parole-pl-parser.c
+parole/parole-about.c
+parole/parole-disc.c
 plugins/properties/stream-properties.c

Modified: parole/trunk/po/parole-media-player.pot
===================================================================
--- parole/trunk/po/parole-media-player.pot	2009-07-23 19:19:54 UTC (rev 7777)
+++ parole/trunk/po/parole-media-player.pot	2009-07-23 21:35:01 UTC (rev 7778)
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-07-19 00:59+0200\n"
+"POT-Creation-Date: 2009-07-23 23:27+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
 "Language-Team: LANGUAGE <LL at li.org>\n"
@@ -48,20 +48,10 @@
 msgid "_View"
 msgstr ""
 
-#: ../data/interfaces/mediachooser.ui.h:1
-#: ../data/interfaces/openlocation.ui.h:2
-#: ../data/interfaces/parole-settings.ui.h:10
-msgid "gtk-close"
-msgstr ""
-
 #: ../data/interfaces/openlocation.ui.h:1
 msgid "Open location of media file or live stream"
 msgstr ""
 
-#: ../data/interfaces/openlocation.ui.h:3
-msgid "gtk-open"
-msgstr ""
-
 #: ../data/interfaces/parole-settings.ui.h:1
 msgid "<b>Audio</b>"
 msgstr ""
@@ -100,119 +90,146 @@
 msgid "Visualization type:"
 msgstr ""
 
-#: ../data/interfaces/parole-settings.ui.h:11
-msgid "gtk-help"
+#: ../data/interfaces/save-playlist.ui.h:1
+msgid "By Extension"
 msgstr ""
 
-#: ../data/desktop/parole.desktop.in.in.h:1 ../parole/parole-player.c:158
+#: ../data/interfaces/save-playlist.ui.h:2
+msgid "Select File Types (By Extension)"
+msgstr ""
+
+#: ../data/desktop/parole.desktop.in.in.h:1 ../parole/parole-player.c:153
 msgid "Parole Media Player"
 msgstr ""
 
-#: ../parole/main.c:103
+#: ../parole/main.c:135
 msgid "Open a new instance"
 msgstr ""
 
-#: ../parole/main.c:104
+#: ../parole/main.c:136
 msgid "Media to play"
 msgstr ""
 
-#: ../parole/main.c:120
+#: ../parole/main.c:152
 #, c-format
 msgid "Type '%s --help' for usage."
 msgstr ""
 
-#: ../parole/parole-gst.c:786
+#: ../parole/parole-gst.c:788
 msgid "Error in changing state to ready"
 msgstr ""
 
-#: ../parole/parole-gst.c:835
+#: ../parole/parole-gst.c:837
 msgid ""
 "Unable to load playbin GStreamer plugin, check your GStreamer installation"
 msgstr ""
 
-#: ../parole/parole-gst.c:850
+#: ../parole/parole-gst.c:852
 msgid ""
 "Unable to load video GStreamer plugin, check your GStreamer installation"
 msgstr ""
 
-#: ../parole/parole-mediachooser.c:203
+#: ../parole/parole-mediachooser.c:173
 msgid "Add media files"
 msgstr ""
 
-#: ../parole/parole-mediachooser.c:203
-msgid "Open media file"
+#: ../parole/parole-mediachooser.c:192
+msgid "Add"
 msgstr ""
 
-#: ../parole/parole-mediachooser.c:220
-msgid "Add"
+#: ../parole/parole-medialist.c:380
+msgid "Error saving playlist file"
 msgstr ""
 
-#: ../parole/parole-mediachooser.c:220
-msgid "Open"
+#: ../parole/parole-medialist.c:380
+msgid "Permission denied"
 msgstr ""
 
-#: ../parole/parole-medialist.c:506
+#: ../parole/parole-medialist.c:389
+msgid "Unknown playlist format, Please select a support playlist format"
+msgstr ""
+
+#: ../parole/parole-medialist.c:455 ../parole/parole-player.c:943
+msgid "Playlist"
+msgstr ""
+
+#: ../parole/parole-medialist.c:462
+msgid "M3U Playlists"
+msgstr ""
+
+#: ../parole/parole-medialist.c:470
+msgid "PLS Playlists"
+msgstr ""
+
+#: ../parole/parole-medialist.c:478
+msgid "Advanced Stream Redirector"
+msgstr ""
+
+#: ../parole/parole-medialist.c:486
+msgid "Shareable Playlist"
+msgstr ""
+
+#: ../parole/parole-medialist.c:760
 msgid "Media list"
 msgstr ""
 
-#: ../parole/parole-player.c:179
+#: ../parole/parole-player.c:174
 msgid "Hide playlist"
 msgstr ""
 
-#: ../parole/parole-player.c:188
+#: ../parole/parole-player.c:183
 msgid "Show playlist"
 msgstr ""
 
-#: ../parole/parole-player.c:334 ../parole/parole-statusbar.c:131
-#: ../parole/parole-statusbar.c:133
+#: ../parole/parole-player.c:335 ../parole/parole-statusbar.c:125
+#: ../parole/parole-statusbar.c:127
 msgid "Playing"
 msgstr ""
 
-#: ../parole/parole-player.c:335
+#: ../parole/parole-player.c:336
 msgid "Media stream is not seekable"
 msgstr ""
 
-#: ../parole/parole-player.c:353 ../parole/parole-player.c:366
+#: ../parole/parole-player.c:354 ../parole/parole-player.c:367
 msgid "Paused"
 msgstr ""
 
-#: ../parole/parole-player.c:384
+#: ../parole/parole-player.c:385
 msgid "Stopped"
 msgstr ""
 
-#: ../parole/parole-player.c:952
-msgid "Playlist"
+#: ../parole/parole-statusbar.c:137
+msgid "Buffering"
 msgstr ""
 
-#: ../parole/parole-sidebar.c:138
-msgid ""
-"<b>Media \n"
-"player\n"
-"</b>"
+#: ../parole/parole-filters.c:57
+msgid "Audio"
 msgstr ""
 
-#: ../parole/parole-sidebar.c:148
-msgid ""
-"<b>Albums\n"
-"</b>"
+#: ../parole/parole-filters.c:75
+msgid "Video"
 msgstr ""
 
-#: ../parole/parole-statusbar.c:143
-msgid "Buffering"
+#: ../parole/parole-filters.c:93
+msgid "Audio and video"
 msgstr ""
 
-#: ../parole/parole-filters.c:46
-msgid "Audio"
+#: ../parole/parole-filters.c:111
+msgid "All supported files"
 msgstr ""
 
-#: ../parole/parole-filters.c:64
-msgid "Video"
+#: ../parole/parole-filters.c:127
+msgid "Playlist files"
 msgstr ""
 
-#: ../parole/parole-filters.c:82
-msgid "Audio and video"
+#: ../parole/parole-about.c:76
+msgid "translator-credits"
 msgstr ""
 
+#: ../parole/parole-disc.c:131
+msgid "Play Disc"
+msgstr ""
+
 #: ../plugins/properties/stream-properties.c:40
 #: ../plugins/properties/stream-properties.c:41
 #: ../plugins/properties/stream-properties.c:42




More information about the Goodies-commits mailing list