Index: configure.ac
===================================================================
--- configure.ac	(révision 4740)
+++ configure.ac	(copie de travail)
@@ -951,6 +951,8 @@
 plugins/artdisplay/artdisplay/Makefile
 plugins/magnatune/Makefile
 plugins/magnatune/magnatune/Makefile
+plugins/jamendo/Makefile
+plugins/jamendo/jamendo/Makefile
 plugins/generic-player/Makefile
 plugins/rb/Makefile
 plugins/power-manager/Makefile
Index: data/rhythmbox.schemas
===================================================================
--- data/rhythmbox.schemas	(révision 4740)
+++ data/rhythmbox.schemas	(copie de travail)
@@ -1045,5 +1045,62 @@
 	</locale>
       </schema>
 
+      <schema>
+        <key>/schemas/apps/rhythmbox/plugins/jamendo/active</key>
+        <applyto>/apps/rhythmbox/plugins/jamendo/active</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>FALSE</default>
+        <locale name="C">
+        <short>True if the jamendo plugin is enabled.</short>
+	<long>True if the jamendo plugin is enabled.</long>
+	</locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/plugins/jamendo/format</key>
+        <applyto>/apps/rhythmbox/plugins/jamendo/format</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>ogg3</default>
+        <locale name="C">
+        <short>Desired format of downloaded audio.</short>
+	<long>Desired format of downloaded audio. Valid values are: ogg3, mp32</long>
+	</locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/plugins/jamendo/sorting</key>
+        <applyto>/apps/rhythmbox/plugins/jamendo/sorting</applyto>
+        <owner>rhythmbox</owner>
+        <type>string</type>
+        <default>Artist,ascending</default>
+        <locale name="C">
+	<short>The sorting order</short>
+	<long>A comma-separated list.  The first is the title of the
+	column to sort on, the second is the sort type.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/plugins/jamendo/show_browser</key>
+        <applyto>/apps/rhythmbox/plugins/jamendo/show_browser</applyto>
+        <owner>rhythmbox</owner>
+        <type>bool</type>
+        <default>TRUE</default>
+        <locale name="C">
+	<short>Whether or not to show the browser.</short>
+	<long>Whether or not to show the browser.</long>
+        </locale>
+      </schema>
+      <schema>
+        <key>/schemas/apps/rhythmbox/plugins/jamendo/paned_position</key>
+        <applyto>/apps/rhythmbox/plugins/jamendo/paned_position</applyto>
+        <owner>rhythmbox</owner>
+        <type>int</type>
+        <default>180</default>
+        <locale name="C">
+	<short>The size of the browser.</short>
+	<long>The size of the browser.</long>
+        </locale>
+      </schema>
+
     </schemalist>
 </gconfschemafile>
Index: po/POTFILES.in
===================================================================
--- po/POTFILES.in	(révision 4740)
+++ po/POTFILES.in	(copie de travail)
@@ -67,6 +67,13 @@
 plugins/ipod/rb-ipod-plugin.c
 plugins/ipod/rb-ipod-source.c
 plugins/iradio/iradio.rb-plugin.desktop.in
+plugins/jamendo/jamendo-loading.glade
+plugins/jamendo/jamendo-prefs.glade
+plugins/jamendo/jamendo.rb-plugin.desktop.in
+plugins/jamendo/jamendo/__init__.py
+plugins/jamendo/jamendo/JamendoConfigureDialog.py
+plugins/jamendo/jamendo/JamendoSaxHandler.py
+plugins/jamendo/jamendo/JamendoSource.py
 plugins/iradio/rb-iradio-source.c
 plugins/iradio/rb-station-properties-dialog.c
 plugins/iradio/station-properties.glade
Index: plugins/jamendo/jamendo-loading.glade
===================================================================
--- plugins/jamendo/jamendo-loading.glade	(révision 0)
+++ plugins/jamendo/jamendo-loading.glade	(révision 0)
@@ -0,0 +1,386 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkWindow" id="window1">
+  <property name="visible">True</property>
+  <property name="title">window1</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="focus_on_map">True</property>
+  <property name="urgency_hint">False</property>
+
+  <child>
+    <widget class="GtkVBox" id="jamendo_loading_vbox">
+      <property name="border_width">12</property>
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">6</property>
+
+      <child>
+	<widget class="GtkImage" id="image1">
+	  <property name="visible">True</property>
+	  <property name="pixbuf">jamendo_logo.png</property>
+	  <property name="xalign">0.5</property>
+	  <property name="yalign">0.5</property>
+	  <property name="xpad">0</property>
+	  <property name="ypad">0</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkLabel" id="label1">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes">&lt;b&gt;Jamendo&lt;/b&gt;</property>
+	  <property name="use_underline">False</property>
+	  <property name="use_markup">True</property>
+	  <property name="justify">GTK_JUSTIFY_CENTER</property>
+	  <property name="wrap">False</property>
+	  <property name="selectable">False</property>
+	  <property name="xalign">0.5</property>
+	  <property name="yalign">0.5</property>
+	  <property name="xpad">0</property>
+	  <property name="ypad">0</property>
+	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	  <property name="width_chars">-1</property>
+	  <property name="single_line_mode">False</property>
+	  <property name="angle">0</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkLabel" id="label2">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes">jamendo is a new model for artists to promote, publish, and be paid for their music.</property>
+	  <property name="use_underline">False</property>
+	  <property name="use_markup">False</property>
+	  <property name="justify">GTK_JUSTIFY_LEFT</property>
+	  <property name="wrap">False</property>
+	  <property name="selectable">False</property>
+	  <property name="xalign">0</property>
+	  <property name="yalign">0.5</property>
+	  <property name="xpad">0</property>
+	  <property name="ypad">0</property>
+	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	  <property name="width_chars">-1</property>
+	  <property name="single_line_mode">False</property>
+	  <property name="angle">0</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkLabel" id="label3">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes">On jamendo, the artists distribute their music under Creative Commons licenses.
+In a nutshell, they allow you to download, remix and share their music freely.
+It's a &quot;Some rights reserved&quot; agreement, perfectly suited for the new century.</property>
+	  <property name="use_underline">False</property>
+	  <property name="use_markup">False</property>
+	  <property name="justify">GTK_JUSTIFY_LEFT</property>
+	  <property name="wrap">False</property>
+	  <property name="selectable">False</property>
+	  <property name="xalign">0</property>
+	  <property name="yalign">0.5</property>
+	  <property name="xpad">0</property>
+	  <property name="ypad">0</property>
+	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	  <property name="width_chars">-1</property>
+	  <property name="single_line_mode">False</property>
+	  <property name="angle">0</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkLabel" id="label4">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes">These new rules make jamendo able to use the new powerful means of digital distribution like
+Peer-to-Peer networks such as BitTorrent or eMule to legally distribute albums at near-zero cost.</property>
+	  <property name="use_underline">False</property>
+	  <property name="use_markup">False</property>
+	  <property name="justify">GTK_JUSTIFY_LEFT</property>
+	  <property name="wrap">False</property>
+	  <property name="selectable">False</property>
+	  <property name="xalign">0</property>
+	  <property name="yalign">0.5</property>
+	  <property name="xpad">0</property>
+	  <property name="ypad">0</property>
+	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	  <property name="width_chars">-1</property>
+	  <property name="single_line_mode">False</property>
+	  <property name="angle">0</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkLabel" id="label5">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes">jamendo users can discover and share albums, but also review them or start a discussion on the forums.
+Albums are democratically rated based on the visitors’ reviews.
+If they fancy an artist they can support him by making a donation.</property>
+	  <property name="use_underline">False</property>
+	  <property name="use_markup">False</property>
+	  <property name="justify">GTK_JUSTIFY_LEFT</property>
+	  <property name="wrap">False</property>
+	  <property name="selectable">False</property>
+	  <property name="xalign">0</property>
+	  <property name="yalign">0.5</property>
+	  <property name="xpad">0</property>
+	  <property name="ypad">0</property>
+	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	  <property name="width_chars">-1</property>
+	  <property name="single_line_mode">False</property>
+	  <property name="angle">0</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkLabel" id="label6">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes">jamendo is the only platform that joins together :</property>
+	  <property name="use_underline">False</property>
+	  <property name="use_markup">False</property>
+	  <property name="justify">GTK_JUSTIFY_LEFT</property>
+	  <property name="wrap">False</property>
+	  <property name="selectable">False</property>
+	  <property name="xalign">0</property>
+	  <property name="yalign">0.5</property>
+	  <property name="xpad">0</property>
+	  <property name="ypad">0</property>
+	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	  <property name="width_chars">-1</property>
+	  <property name="single_line_mode">False</property>
+	  <property name="angle">0</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkTable" id="table1">
+	  <property name="visible">True</property>
+	  <property name="n_rows">5</property>
+	  <property name="n_columns">1</property>
+	  <property name="homogeneous">False</property>
+	  <property name="row_spacing">0</property>
+	  <property name="column_spacing">0</property>
+
+	  <child>
+	    <widget class="GtkLabel" id="label8">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">     * Free, simple and quick access to the music, for everyone.</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="left_attach">0</property>
+	      <property name="right_attach">1</property>
+	      <property name="top_attach">1</property>
+	      <property name="bottom_attach">2</property>
+	      <property name="x_options">fill</property>
+	      <property name="y_options"></property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label9">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes" comments="This text comes from http://www.jamendo.com/en/static/concept/ and was already translated in many languages.
+You should take a look on this site and check if you can't reuse it.">     * A legal framework protecting the artists (thanks to the Creative Commons licenses).</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="left_attach">0</property>
+	      <property name="right_attach">1</property>
+	      <property name="top_attach">0</property>
+	      <property name="bottom_attach">1</property>
+	      <property name="x_options">fill</property>
+	      <property name="y_options"></property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label10">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">     * The use of the lastest Peer-to-Peer technologies</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="left_attach">0</property>
+	      <property name="right_attach">1</property>
+	      <property name="top_attach">2</property>
+	      <property name="bottom_attach">3</property>
+	      <property name="x_options">fill</property>
+	      <property name="y_options"></property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label11">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">     * The possibility of making direct donations to the artists.</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="left_attach">0</property>
+	      <property name="right_attach">1</property>
+	      <property name="top_attach">3</property>
+	      <property name="bottom_attach">4</property>
+	      <property name="x_options">fill</property>
+	      <property name="y_options"></property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label12">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">     * An adaptive music recommendation system based on iRATE to help listeners discover new artists based on their tastes
+       and on other criterias such as their location.</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">False</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="left_attach">0</property>
+	      <property name="right_attach">1</property>
+	      <property name="top_attach">4</property>
+	      <property name="bottom_attach">5</property>
+	      <property name="x_options">fill</property>
+	      <property name="y_options"></property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkLabel" id="label7">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes">You can find more information at http://www.jamendo.com/</property>
+	  <property name="use_underline">False</property>
+	  <property name="use_markup">False</property>
+	  <property name="justify">GTK_JUSTIFY_CENTER</property>
+	  <property name="wrap">False</property>
+	  <property name="selectable">False</property>
+	  <property name="xalign">0.5</property>
+	  <property name="yalign">0.5</property>
+	  <property name="xpad">0</property>
+	  <property name="ypad">0</property>
+	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	  <property name="width_chars">-1</property>
+	  <property name="single_line_mode">False</property>
+	  <property name="angle">0</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
Index: plugins/jamendo/jamendo-prefs.glade
===================================================================
--- plugins/jamendo/jamendo-prefs.glade	(révision 0)
+++ plugins/jamendo/jamendo-prefs.glade	(révision 0)
@@ -0,0 +1,221 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+<requires lib="gnome"/>
+
+<widget class="GtkDialog" id="preferences_dialog">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Jamendo Preferences</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="decorated">True</property>
+  <property name="skip_taskbar_hint">False</property>
+  <property name="skip_pager_hint">False</property>
+  <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+  <property name="focus_on_map">True</property>
+  <property name="urgency_hint">False</property>
+  <property name="has_separator">True</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+	<widget class="GtkHButtonBox" id="dialog-action_area1">
+	  <property name="visible">True</property>
+	  <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+	  <child>
+	    <widget class="GtkButton" id="closebutton1">
+	      <property name="visible">True</property>
+	      <property name="can_default">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-close</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <property name="response_id">-7</property>
+	    </widget>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	  <property name="pack_type">GTK_PACK_END</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkVBox" id="jamendo_vbox">
+	  <property name="border_width">5</property>
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">18</property>
+
+	  <child>
+	    <widget class="GtkImage" id="image1">
+	      <property name="visible">True</property>
+	      <property name="pixbuf">jamendo_logo_medium.png</property>
+	      <property name="xalign">0.5</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label58">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">&lt;b&gt;Download&lt;/b&gt;</property>
+	      <property name="use_underline">False</property>
+	      <property name="use_markup">True</property>
+	      <property name="justify">GTK_JUSTIFY_LEFT</property>
+	      <property name="wrap">False</property>
+	      <property name="selectable">False</property>
+	      <property name="xalign">0</property>
+	      <property name="yalign">0.5</property>
+	      <property name="xpad">0</property>
+	      <property name="ypad">0</property>
+	      <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	      <property name="width_chars">-1</property>
+	      <property name="single_line_mode">False</property>
+	      <property name="angle">0</property>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkHBox" id="hbox21">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<widget class="GtkLabel" id="audio_label">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">_Format:</property>
+		  <property name="use_underline">True</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">8</property>
+		  <property name="ypad">0</property>
+		  <property name="mnemonic_widget">audio_combobox</property>
+		  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		  <property name="width_chars">-1</property>
+		  <property name="single_line_mode">False</property>
+		  <property name="angle">0</property>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GtkComboBox" id="audio_combobox">
+		  <property name="visible">True</property>
+		  <property name="items" translatable="yes">Ogg Vorbis (300Kbps)
+MP3 (200Kbps)</property>
+		  <property name="add_tearoffs">False</property>
+		  <property name="focus_on_click">True</property>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">True</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkHBox" id="hbox23">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<widget class="GtkLabel" id="label57">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Visit Jamendo at </property>
+		  <property name="use_underline">False</property>
+		  <property name="use_markup">False</property>
+		  <property name="justify">GTK_JUSTIFY_LEFT</property>
+		  <property name="wrap">False</property>
+		  <property name="selectable">False</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xpad">0</property>
+		  <property name="ypad">0</property>
+		  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+		  <property name="width_chars">-1</property>
+		  <property name="single_line_mode">False</property>
+		  <property name="angle">0</property>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">False</property>
+		</packing>
+	      </child>
+
+	      <child>
+		<widget class="GnomeHRef" id="href1">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="url">http://www.jamendo.com/</property>
+		  <property name="text" translatable="yes">http://www.jamendo.com/</property>
+		  <property name="focus_on_click">True</property>
+		</widget>
+		<packing>
+		  <property name="padding">0</property>
+		  <property name="expand">False</property>
+		  <property name="fill">False</property>
+		</packing>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">True</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
Index: plugins/jamendo/jamendo.rb-plugin.desktop.in
===================================================================
--- plugins/jamendo/jamendo.rb-plugin.desktop.in	(révision 0)
+++ plugins/jamendo/jamendo.rb-plugin.desktop.in	(révision 0)
@@ -0,0 +1,9 @@
+[RB Plugin]
+Loader=python
+Module=jamendo
+IAge=1
+_Name=Jamendo
+_Description=Adds support to Rhythmbox for playing and downloading albums from Jamendo
+Authors=Guillaume Desmottes
+Copyright=Copyright © 2007 Guillaume Desmottes
+Website=http://www.rhythmbox.org/
Index: plugins/jamendo/Makefile.am
===================================================================
--- plugins/jamendo/Makefile.am	(révision 0)
+++ plugins/jamendo/Makefile.am	(révision 0)
@@ -0,0 +1,24 @@
+# Jamendo Python Plugin
+
+SUBDIRS = jamendo
+
+plugindir = $(PLUGINDIR)/jamendo
+
+%.rb-plugin: %.rb-plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+plugin_DATA = $(plugin_in_files:.rb-plugin.desktop.in=.rb-plugin)
+
+
+plugin_in_files = jamendo.rb-plugin.desktop.in
+
+glade_DATA =	\
+		jamendo-loading.glade                 \
+		jamendo-prefs.glade		      \
+		jamendo_logo.png		      \
+		jamendo_logo_medium.png		      \
+		jamendo_logo_small.png			
+
+gladedir = $(plugindir)
+EXTRA_DIST = $(plugin_in_files) $(glade_DATA)
+CLEANFILES = $(plugin_DATA)
+DISTCLEANFILES = $(plugin_DATA)
+
Index: plugins/jamendo/jamendo/JamendoSource.py
===================================================================
--- plugins/jamendo/jamendo/JamendoSource.py	(révision 0)
+++ plugins/jamendo/jamendo/JamendoSource.py	(révision 0)
@@ -0,0 +1,382 @@
+# -*- coding: utf-8 -*-
+
+# JamendoSource.py
+#
+# Copyright (C) 2007 - Guillaume Desmottes
+#
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Parts from "Magnatune Rhythmbox plugin" (stolen from rhythmbox's MagnatuneSource.py)
+#     Copyright (C), 2006 Adam Zimmerman <adam_zimmerman@sfu.ca>
+
+import rb, rhythmdb
+from JamendoSaxHandler import JamendoSaxHandler
+import JamendoConfigureDialog
+
+import gobject
+import gtk.glade
+import gnomevfs, gnome, gconf
+import xml
+import gzip
+
+# URIs
+jamendo_dir = gnome.user_dir_get() + "rhythmbox/jamendo/"
+jamendo_song_info_uri = gnomevfs.URI("http://img.jamendo.com/data/dbdump.en.xml.gz")
+local_song_info_uri = gnomevfs.URI(jamendo_dir + "dbdump.en.xml")
+local_song_info_temp_uri = gnomevfs.URI(jamendo_dir + "dbdump.en.xml.tmp")
+
+stream_url = "http://www.jamendo.com/get/track/id/track/audio/redirect/%s/?aue=ogg2"
+
+class JamendoSource(rb.BrowserSource):
+	__gproperties__ = {
+		'plugin': (rb.Plugin, 'plugin', 'plugin', gobject.PARAM_WRITABLE|gobject.PARAM_CONSTRUCT_ONLY),
+	}
+
+	def __init__(self):
+
+		rb.BrowserSource.__init__(self, name=_("Jamendo"))
+
+		self.__p2plinks = {}
+
+		# catalogue stuff
+		self.__saxHandler = None
+		self.__activated = False
+		self.__notify_id = 0
+		self.__update_id = 0
+		self.__xfer_handle = None
+		self.__info_screen = None
+		self.__updating = True
+		self.__load_handle = None
+		self.__load_current_size = 0
+		self.__load_total_size = 0
+		
+	def do_set_property(self, property, value):
+		if property.name == 'plugin':
+			self.__plugin = value
+
+			# we have to wait until we get the plugin to do this
+			circle_file_name = self.__plugin.find_file("jamendo_logo_small.png")
+			width, height = gtk.icon_size_lookup(gtk.ICON_SIZE_LARGE_TOOLBAR)
+			icon = gtk.gdk.pixbuf_new_from_file_at_size(circle_file_name, width, height)
+			self.set_property("icon", icon)
+
+		else:
+			raise AttributeError, 'unknown property %s' % property.name
+
+	#def do_impl_get_browser_key (self):
+	#	return "/apps/rhythmbox/plugins/jamendo/show_browser"
+
+	#def do_impl_get_paned_key (self):
+	#	return "/apps/rhythmbox/plugins/jamendo/paned_position"
+
+
+	#
+	# RBSource methods
+	#
+
+	def do_impl_show_entry_popup(self):
+		self.show_source_popup ("/JamendoSourceViewPopup")
+
+	def do_impl_get_ui_actions(self):
+		return ["JamendoDownloadAlbum"]
+
+
+	def do_impl_get_status(self):
+		if self.__updating:
+			if self.__load_total_size > 0:
+				progress = min (float(self.__load_current_size) / self.__load_total_size, 1.0)
+			else:
+				progress = -1.0
+			return (_("Loading Jamendo catalogue"), None, progress)
+		else:
+			qm = self.get_property("query-model")
+			return (qm.compute_status_normal(_("%d song"), _("%d songs")), None, 0.0)
+	
+	def do_impl_activate(self):
+		if not self.__activated:
+			shell = self.get_property('shell')
+			self.__db = shell.get_property('db')
+			self.__entry_type = self.get_property('entry-type')
+
+			self.__activated = True
+			self.__show_loading_screen (True)
+			self.__load_catalogue()
+
+			# start our catalogue updates
+			self.__update_id = gobject.timeout_add(6 * 60 * 60 * 1000, self.__update_catalogue)
+			self.__update_catalogue()
+			
+			sort_key = gconf.client_get_default().get_string(JamendoConfigureDialog.gconf_keys['sorting'])
+			if not sort_key:
+				sort_key = "Artist,ascending"
+			self.get_entry_view().set_sorting_type(sort_key)
+
+		rb.BrowserSource.do_impl_activate (self)
+	
+	def do_impl_delete_thyself(self):
+		if self.__update_id != 0:
+			gobject.source_remove (self.__update_id)
+			self.__update_id = 0
+
+		if self.__notify_id != 0:
+			gobject.source_remove (self.__notify_id)
+			self.__notify_id = 0
+
+		if self.__xfer_handle is not None:
+			self.__xfer_handle.close(lambda handle, exc: None) #FIXME: report it?
+			self.__xfer_handle = None
+		
+		gconf.client_get_default().set_string(JamendoConfigureDialog.gconf_keys['sorting'], self.get_entry_view().get_sorting_type())
+		rb.BrowserSource.do_impl_delete_thyself (self)
+
+
+	#
+	# internal catalogue downloading and loading
+	#
+	def __load_catalogue_read_cb (self, handle, data, exc_type, bytes_requested, parser):
+		if exc_type:
+			if issubclass (exc_type, gnomevfs.EOFError):
+				def finish_loadscreen():
+					# successfully loaded
+					gtk.gdk.threads_enter()
+					self.__load_db ()
+					self.__show_loading_screen (False)
+				
+					in_progress_dir = gnomevfs.DirectoryHandle(gnomevfs.URI(jamendo_dir))
+					in_progress = in_progress_dir.next()
+					while True:
+						if in_progress.name[0:12] == "in_progress_":
+							in_progress = gnomevfs.read_entire_file(jamendo_dir + in_progress.name)
+							for uri in in_progress.split("\n"):
+								if uri == '':
+									continue
+								self.__download_album(gnomevfs.URI(uri))
+						try:
+							in_progress = in_progress_dir.next()
+						except:
+							break
+					gtk.gdk.threads_leave()
+				gobject.idle_add (finish_loadscreen)
+			else:
+				# error reading file
+				raise exc_type
+			
+			parser.close()
+			handle.close(lambda handle, exc: None) # FIXME: report it?
+			self.__load_handle = None
+			self.__updating = False
+			self.__notify_status_changed()
+ 		else:
+
+			parser.feed(data)
+			handle.read(64 * 1024, self.__load_catalogue_read_cb, parser)
+
+		self.__notify_status_changed()
+
+	def __load_catalogue_open_cb (self, handle, exc_type):
+		if exc_type:
+			self.__load_handle = None
+			self.__notify_status_changed()
+			
+			if gnomevfs.exists(local_song_info_uri):
+				raise exc_type
+			else:
+				return
+
+		parser = xml.sax.make_parser()
+		self.__saxHandler = JamendoSaxHandler()
+		parser.setContentHandler(self.__saxHandler)
+		handle.read (64 * 1024, self.__load_catalogue_read_cb, parser)
+
+	def __load_catalogue(self):
+		self.__notify_status_changed()
+		self.__load_handle = gnomevfs.async.open (local_song_info_uri, self.__load_catalogue_open_cb)
+
+
+	def __download_update_cb (self, _reserved, info, moving):
+		if info.phase == gnomevfs.XFER_PHASE_COMPLETED:
+			# done downloading, unzip to real location
+			catalog = gzip.open(local_song_info_temp_uri.path)
+			out = create_if_needed(local_song_info_uri, gnomevfs.OPEN_WRITE)
+			out.write(catalog.read())
+			out.close()
+			catalog.close()
+			gnomevfs.unlink(local_song_info_temp_uri)
+			self.__updating = False
+			self.__load_catalogue()
+		else:
+			#print info
+			pass
+
+		return 1
+
+	def __download_progress_cb (self, info, data):
+		#if info.status == gnomevfs.XFER_PROGRESS_STATUS_OK:
+		if True:
+			self.__load_current_size = info.bytes_copied
+			self.__load_total_size = info.bytes_total
+			self.__notify_status_changed()
+		else:
+			print info
+		return 1
+
+	def __download_catalogue(self):
+		self.__updating = True
+		create_if_needed(local_song_info_temp_uri, gnomevfs.OPEN_WRITE).close()
+		self.__xfer_handle = gnomevfs.async.xfer (source_uri_list = [jamendo_song_info_uri],
+							  target_uri_list = [local_song_info_temp_uri],
+							  xfer_options = gnomevfs.XFER_FOLLOW_LINKS_RECURSIVE,
+							  error_mode = gnomevfs.XFER_ERROR_MODE_ABORT,
+							  overwrite_mode = gnomevfs.XFER_OVERWRITE_MODE_REPLACE,
+							  progress_update_callback = self.__download_update_cb,
+							  update_callback_data = False,
+							  progress_sync_callback = self.__download_progress_cb,
+							  sync_callback_data = None)
+
+	def __update_catalogue(self):
+		def info_cb (handle, results):
+			(remote_uri, remote_exc, remote_info) = results[0]
+			(local_uri, local_exc, local_info) = results[1]
+
+			if remote_exc:
+				# error locating remote file
+				print "error locating remote catalogue", remote_exc
+			elif local_exc:
+				if issubclass (local_exc, gnomevfs.NotFoundError):
+					# we haven't got it yet
+					print "no local copy of catalogue"
+					self.__download_catalogue()
+				else:
+					# error locating local file
+					print "error locating local catalogue", local_exc
+					self.__download_catalogue()
+			else:
+				try:
+					if remote_info.mtime > local_info.mtime:
+						# newer version available
+						self.__download_catalogue()
+					else:
+						# up to date
+						pass
+				except ValueError, e:
+					# couldn't get the mtimes. download?
+					print "error checking times", e
+					self.__download_catalogue()
+			return
+
+		gnomevfs.async.get_file_info ((jamendo_song_info_uri, local_song_info_uri), info_cb)
+
+	def __show_loading_screen(self, show):
+		if self.__info_screen is None:
+			# load the glade stuff
+			gladexml = gtk.glade.XML(self.__plugin.find_file("jamendo-loading.glade"), root="jamendo_loading_vbox")
+			self.__info_screen = gladexml.get_widget("jamendo_loading_vbox")
+			self.pack_start(self.__info_screen)
+			self.get_entry_view().set_no_show_all (True)
+			self.__info_screen.set_no_show_all (True)
+
+		self.__info_screen.set_property("visible", show)
+		self.get_entry_view().set_property("visible", not show)
+
+	def __load_db(self):
+		tracks = self.__saxHandler.tracks
+		albums = self.__saxHandler.albums
+		artists = self.__saxHandler.artists
+
+		for track_key in tracks.keys():
+			track = tracks[track_key]
+			album = albums[track['albumID']]
+			artist = artists[album['artistID']]
+			stream = stream_url % (track_key)
+	
+			entry = self.__db.entry_lookup_by_location (stream)
+			if entry == None:
+				entry = self.__db.entry_new(self.__entry_type, stream)
+			self.__db.set(entry, rhythmdb.PROP_TITLE, track['dispname'])
+			self.__db.set(entry, rhythmdb.PROP_ARTIST, artist['dispname'])
+			self.__db.set(entry, rhythmdb.PROP_ALBUM, album['dispname'])
+			self.__db.set(entry, rhythmdb.PROP_TRACK_NUMBER, int(track['trackno']))
+			self.__db.set(entry, rhythmdb.PROP_DURATION, int(track['lengths']))
+			self.__db.set(entry, rhythmdb.PROP_GENRE, artist['genre'])
+
+			self.__p2plinks[stream] = album['P2PLinks']
+
+		self.__db.commit()
+		self.__saxHandler = None
+
+
+	def __notify_status_changed(self):
+		def change_idle_cb():
+			self.notify_status_changed()
+			self.__notify_id = 0
+			return False
+
+		if self.__notify_id == 0:
+			self.__notify_id = gobject.idle_add(change_idle_cb)
+
+
+	# Download album
+	def download_album (self):
+		tracks = self.get_entry_view().get_selected_entries()
+		format = gconf.client_get_default().get_string(JamendoConfigureDialog.gconf_keys['format'])
+		if not format or format not in JamendoConfigureDialog.format_list:
+			format = 'ogg3'
+
+		#TODO: this should work if the album was selected in the browser
+		#without any track selected
+		if len(tracks) == 1:
+			track = tracks[0]
+			stream = self.__db.entry_get(track, rhythmdb.PROP_LOCATION)
+			for p2plink in self.__p2plinks[stream]:
+				if p2plink['network'] == 'bittorrent' and p2plink['audioEncoding'] == format:
+					break
+			self.__download_p2plink (p2plink['p2plink'])
+	
+	def __download_p2plink (self, link):
+		gnomevfs.url_show(link)
+
+
+	def __p2plink_download_update_cb (self, _reserved, info, moving):
+		if info.phase == gnomevfs.XFER_PHASE_COMPLETED:
+			print info
+
+		return 1
+
+gobject.type_register(JamendoSource)
+
+def create_if_needed(uri, mode):
+	if not gnomevfs.exists(uri):
+		for directory in URIIterator(uri):
+			if not gnomevfs.exists(directory):
+				gnomevfs.make_directory(directory, 0755)
+		out = gnomevfs.create(uri, open_mode=mode)
+	else:
+		out = gnomevfs.open(uri, open_mode=mode)
+	return out
+
+class URIIterator:
+	def __init__(self, uri):
+		self.uri_list = uri.dirname.split("/")[1:] # dirname starts with /
+		self.counter = 0
+	def __iter__(self):
+		return self
+	def next(self):
+		if self.counter == len(self.uri_list) + 1:
+			raise StopIteration
+		value = "file://"
+		for i in range(self.counter):
+			value += "/" + self.uri_list[i]
+		self.counter += 1
+		return gnomevfs.URI(value)
Index: plugins/jamendo/jamendo/JamendoConfigureDialog.py
===================================================================
--- plugins/jamendo/jamendo/JamendoConfigureDialog.py	(révision 0)
+++ plugins/jamendo/jamendo/JamendoConfigureDialog.py	(révision 0)
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+
+# JamendoConfigureDialog.py
+#
+# Copyright (C) 2007 - Guillaume Desmottes
+#
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+import gobject
+import gtk, gtk.glade
+import gconf, gnomevfs, gnome
+
+gconf_keys = {	'format' : '/apps/rhythmbox/plugins/jamendo/format',
+		'sorting': '/apps/rhythmbox/plugins/jamendo/sorting'
+	     }
+format_list = ['ogg3', 'mp32']
+
+class JamendoConfigureDialog (object):
+	def __init__(self, glade_file):
+		self.gconf = gconf.client_get_default()
+		gladexml = gtk.glade.XML(glade_file)
+
+		self.dialog = gladexml.get_widget('preferences_dialog')
+		self.audio_combobox = gladexml.get_widget("audio_combobox")
+
+		format_text = self.gconf.get_string(gconf_keys['format'])
+		if not format_text:
+			format_text = "ogg3"
+		try:
+			format = format_list.index(format_text)
+		except ValueError:
+			format = 0
+		self.audio_combobox.set_active(format)
+
+		self.dialog.connect("response", self.dialog_response)
+		self.audio_combobox.connect("changed", self.audio_combobox_changed)
+
+	def get_dialog (self):
+		return self.dialog
+
+	def dialog_response (self, dialog, response):
+		dialog.hide()
+
+	def audio_combobox_changed (self, combobox):
+		format = self.audio_combobox.get_active()
+		self.gconf.set_string(gconf_keys['format'], format_list[format])
Index: plugins/jamendo/jamendo/__init__.py
===================================================================
--- plugins/jamendo/jamendo/__init__.py	(révision 0)
+++ plugins/jamendo/jamendo/__init__.py	(révision 0)
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+
+# __init__.py
+#
+# Copyright (C) 2007 - Guillaume Desmottes
+#
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Parts from "Magnatune Rhythmbox plugin" (stolen from rhythmbox's __init__.py)
+#     Copyright (C), 2006 Adam Zimmerman <adam_zimmerman@sfu.ca>
+
+import rhythmdb, rb
+import gobject
+import gtk, gtk.glade
+
+from JamendoSource import JamendoSource
+from JamendoConfigureDialog import JamendoConfigureDialog
+
+popup_ui = """
+<ui>
+  <popup name="JamendoSourceViewPopup">
+    <menuitem name="AddToQueueLibraryPopup" action="AddToQueue"/>
+    <menuitem name="JamendoDownloadAlbum" action="JamendoDownloadAlbum"/>
+    <separator/>
+    <menuitem name="BrowseGenreLibraryPopup" action="BrowserSrcChooseGenre"/>
+    <menuitem name="BrowseArtistLibraryPopup" action="BrowserSrcChooseArtist"/>
+    <menuitem name="BrowseAlbumLibraryPopup" action="BrowserSrcChooseAlbum"/>
+    <separator/>
+    <menuitem name="PropertiesLibraryPopup" action="MusicProperties"/>
+  </popup>
+</ui>
+"""
+
+
+class Jamendo(rb.Plugin):
+	#
+	# Core methods
+	#
+	
+	def __init__(self):
+		rb.Plugin.__init__(self)
+		
+	def activate(self, shell):
+		self.db = shell.get_property("db")
+
+		self.entry_type = self.db.entry_register_type("JamendoEntryType")
+		# allow changes which don't do anything
+		self.entry_type.can_sync_metadata = True
+		self.entry_type.sync_metadata = None
+
+		self.source = gobject.new (JamendoSource, shell=shell, entry_type=self.entry_type, plugin=self)
+		shell.register_entry_type_for_source(self.source, self.entry_type)
+		shell.append_source(self.source, None) # Add the source to the list
+
+		# Add button
+		manager = shell.get_player().get_property('ui-manager')
+		action = gtk.Action('JamendoDownloadAlbum', _('_Download Album'),
+				_("Download this album using BitTorrent"),
+				'gtk-save')
+		action.connect('activate', lambda a: shell.get_property("selected-source").download_album())
+		self.action_group = gtk.ActionGroup('JamendoPluginActions')
+		self.action_group.add_action(action)
+
+		manager.insert_action_group(self.action_group, 0)
+		self.ui_id = manager.add_ui_from_string(popup_ui)
+		manager.ensure_update()
+
+	def deactivate(self, shell):
+		manager = shell.get_player().get_property('ui-manager')
+		manager.remove_ui (self.ui_id)
+		manager.remove_action_group(self.action_group)
+		self.action_group = None
+
+		self.db.entry_delete_by_type(self.entry_type)
+		self.db.commit()
+		self.db = None
+		self.entry_type = None
+
+		self.source.delete_thyself()
+		self.source = None
+
+	def create_configure_dialog(self, dialog=None):
+		if not dialog:
+			glade_file = self.find_file("jamendo-prefs.glade")
+			dialog = JamendoConfigureDialog (glade_file).get_dialog()
+		dialog.present()
+		return dialog
Index: plugins/jamendo/jamendo/Makefile.am
===================================================================
--- plugins/jamendo/jamendo/Makefile.am	(révision 0)
+++ plugins/jamendo/jamendo/Makefile.am	(révision 0)
@@ -0,0 +1,8 @@
+# Jamendo Python Plugin
+
+plugindir = $(PLUGINDIR)/jamendo
+plugin_PYTHON =                       \
+       JamendoSource.py	              \
+       JamendoSaxHandler.py	      \
+       JamendoConfigureDialog.py      \
+       __init__.py
Index: plugins/jamendo/jamendo/JamendoSaxHandler.py
===================================================================
--- plugins/jamendo/jamendo/JamendoSaxHandler.py	(révision 0)
+++ plugins/jamendo/jamendo/JamendoSaxHandler.py	(révision 0)
@@ -0,0 +1,153 @@
+# -*- coding: utf-8 -*-
+
+# JamendoSaxHandler.py
+#
+# Copyright (C) 2007 - Guillaume Desmottes
+#
+# 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+import xml.sax, xml.sax.handler
+
+markups = ["JamendoData", "Artists", "artist", "Albums", "album", "Covers", "cover", "P2PLinks", "p2plink", "Tracks", "track"]
+
+class JamendoSaxHandler(xml.sax.handler.ContentHandler):
+	def __init__(self):
+		xml.sax.handler.ContentHandler.__init__(self)
+
+		self.current = {}
+
+	def startElement(self, name, attrs):
+		self.__text = ""
+
+		if name in markups:
+			fct = getattr (self, "start" + name)
+			fct (attrs)
+	
+	def endElement(self, name):
+		if name in markups:
+			fct = getattr (self, "end" + name)
+			fct ()
+		else:
+			self.current[name] = self.__text
+	
+	def characters(self, content):
+		self.__text = self.__text + content
+
+	# start markups
+	def startJamendoData (self, attrs):
+		pass
+
+	def startArtists (self, attrs):
+		self.artists = {}	
+
+	def startartist (self, attrs):
+		self.artist = {}	
+		for attr in attrs.getNames():
+			self.artist[attr] = attrs[attr]
+		self.current = self.artist
+
+	def startAlbums (self, attrs):
+		self.albums = {}
+
+	def startalbum (self, attrs):
+		self.album = {}
+		for attr in attrs.getNames():
+			self.album[attr] = attrs[attr]
+		self.current = self.album
+
+	def startCovers (self, attrs):
+		# we create a list to store all the covers
+		# of this album
+		self.album['Covers'] = []
+
+	def startcover (self, attrs):
+		self.cover = {}
+		for attr in attrs.getNames():
+			self.cover[attr] = attrs[attr]
+
+	def startP2PLinks (self, attrs):
+		self.album['P2PLinks'] = []
+
+	def startp2plink (self, attrs):
+		self.p2plink = {}
+		for attr in attrs.getNames():
+			self.p2plink[attr] = attrs[attr]
+
+	def startTracks (self, attrs):
+		self.tracks = {}
+
+	def starttrack (self, attrs):
+		self.track = {}
+		for attr in attrs.getNames():
+			self.track[attr] = attrs[attr]
+		self.current = self.track
+
+	# end markups
+	def endJamendoData (self):
+		pass # end of file
+
+	def endArtists (self):
+		pass # we have load all artists
+
+	def endartist (self):
+		self.artists[self.artist['id']] = self.artist
+
+	def endAlbums (self):
+		pass # we have load all albums
+
+	def endalbum (self):
+		self.albums[self.album['id']] = self.album
+
+	def endCovers (self):
+		pass # we have load all covers of this album
+
+	def endcover (self):
+		self.cover["cover"] = self.__text
+		self.album["Covers"].append(self.cover)
+
+	def endP2PLinks (self):
+		pass # we have load all links of this album
+
+	def endp2plink (self):
+		self.p2plink["p2plink"] = self.__text
+		self.album["P2PLinks"].append(self.p2plink)
+
+	def endTracks (self):
+		pass #we have load all the tracks of this album
+
+	def endtrack (self):
+		self.tracks[self.track['id']] = self.track
+
+
+if __name__ == "__main__":
+	parser = xml.sax.make_parser()
+	handler = JamendoSaxHandler()
+	parser.setContentHandler(handler)
+	datasource = open("/tmp/dbdump.en.xml")
+	#datasource = open("exemple_jamendo.xml")
+	parser.parse(datasource)
+	#print handler.artists
+	#print handler.albums
+	#print handler.tracks
+
+	tracks = handler.tracks
+	artists = handler.artists
+	albums = handler.albums
+	for track_key in tracks.keys():
+		track = tracks[track_key]
+		album = albums[track['albumID']]
+		artist = artists[album['artistID']]
+		#print track['dispname'], track['trackno'], track['lengths'], album['dispname'], artist['dispname']
+		print album['P2PLinks']
Index: plugins/Makefile.am
===================================================================
--- plugins/Makefile.am	(révision 4740)
+++ plugins/Makefile.am	(copie de travail)
@@ -20,6 +20,7 @@
 	artdisplay					\
 	lyrics						\
 	magnatune					\
+	jamendo						\
 	rb
 endif
 
