diff -u -p -r1.248 configure.ac
--- configure.ac	24 Jun 2006 23:07:04 -0000	1.248
+++ configure.ac	30 Jun 2006 04:42:39 -0000
@@ -924,6 +924,8 @@ plugins/sample-python/Makefile
 plugins/pythonconsole/Makefile
 plugins/artdisplay/Makefile
 plugins/artdisplay/artdisplay/Makefile
+plugins/magnatune/Makefile
+plugins/magnatune/magnatune/Makefile
 plugins/generic-player/Makefile
 bindings/Makefile
 bindings/python/Makefile
diff -u -p -r1.8 Makefile.am
--- plugins/Makefile.am	25 May 2006 07:20:47 -0000	1.8
+++ plugins/Makefile.am	30 Jun 2006 04:42:39 -0000
@@ -17,6 +17,7 @@ SUBDIRS += 						\
 	pythonconsole					\
 	sample-python					\
 	artdisplay					\
+	magnatune					\
 	lyrics
 endif
 
--- /dev/null	2006-05-23 00:25:23.000000000 +1000
+++ plugins/magnatune/magnatune.rb-plugin.desktop.in	2006-06-29 15:15:44.000000000 +1000
@@ -0,0 +1,9 @@
+[RB Plugin]
+Loader=python
+Module=magnatune
+IAge=1
+_Name=Magnatune Store
+_Description=Adds support to Rhythmbox for playing and purchasing from the Magnatune online music store
+Authors=Adam Zimmerman
+Copyright=(C) 2006 Adam Zimmerman
+Website=http://www.rhythmbox.org/
--- /dev/null	2006-05-23 00:25:23.000000000 +1000
+++ plugins/magnatune/Makefile.am	2006-06-29 15:58:40.000000000 +1000
@@ -0,0 +1,22 @@
+# Magnatune Store Python Plugin
+
+SUBDIRS = magnatune
+
+plugindir = $(PLUGINDIR)
+
+%.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 = magnatune.rb-plugin.desktop.in
+
+glade_DATA =	\
+		magnatune-confirm.glade			\
+		magnatune-download.glade		\
+		magnatune-prefs.glade
+
+gladedir = $(pkgdatadir)/glade
+EXTRA_DIST = $(plugin_in_files) $(glade_DATA)
+CLEANFILES = $(plugin_DATA)
+DISTCLEANFILES = $(plugin_DATA)
+
--- /dev/null	2006-05-23 00:25:23.000000000 +1000
+++ plugins/magnatune/magnatune-confirm.glade	2006-06-29 05:10:10.000000000 +1000
@@ -0,0 +1,333 @@
+<?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="confirm_window">
+  <property name="visible">False</property>
+  <property name="title" translatable="yes">Confirm Purchase</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_CENTER</property>
+  <property name="modal">True</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="vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">4</property>
+
+      <child>
+	<widget class="GtkLabel" id="info_label">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes">You are about to purchase the album &quot;&quot; by &quot;&quot;.</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">8</property>
+	  <property name="ypad">8</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">2</property>
+	  <property name="n_columns">3</property>
+	  <property name="homogeneous">False</property>
+	  <property name="row_spacing">0</property>
+	  <property name="column_spacing">0</property>
+
+	  <child>
+	    <widget class="GtkLabel" id="label2">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes"></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">12</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">2</property>
+	      <property name="x_options">fill</property>
+	      <property name="y_options"></property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="pay_label">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Pay:</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">8</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">1</property>
+	      <property name="right_attach">2</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="GtkComboBox" id="pay_combobox">
+	      <property name="visible">True</property>
+	      <property name="items" translatable="yes">$5
+$6
+$7
+$8 (typical)
+$9
+$10 (better than average)
+$11
+$12 (generous)
+$13
+$14
+$15 (VERY generous!)
+$16
+$17
+$18 (We love you!)</property>
+	      <property name="add_tearoffs">False</property>
+	      <property name="focus_on_click">True</property>
+	    </widget>
+	    <packing>
+	      <property name="left_attach">2</property>
+	      <property name="right_attach">3</property>
+	      <property name="top_attach">0</property>
+	      <property name="bottom_attach">1</property>
+	      <property name="x_options">fill</property>
+	      <property name="y_options">fill</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="audio_label">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Preferred Audio Format:</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">8</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">1</property>
+	      <property name="right_attach">2</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="GtkComboBox" id="audio_combobox">
+	      <property name="visible">True</property>
+	      <property name="items" translatable="yes">Ogg Vorbis
+FLAC
+WAV
+VBR MP3
+128K MP3</property>
+	      <property name="add_tearoffs">False</property>
+	      <property name="focus_on_click">True</property>
+	    </widget>
+	    <packing>
+	      <property name="left_attach">2</property>
+	      <property name="right_attach">3</property>
+	      <property name="top_attach">1</property>
+	      <property name="bottom_attach">2</property>
+	      <property name="x_options">fill</property>
+	      <property name="y_options">fill</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHSeparator" id="hseparator1">
+	  <property name="visible">True</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHBox" id="hbox1">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">6</property>
+
+	  <child>
+	    <widget class="GtkButton" id="button1">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <signal name="clicked" handler="rb_magnatune_purchase_button_clicked_cb" last_modification_time="Mon, 26 Jun 2006 22:24:38 GMT"/>
+
+	      <child>
+		<widget class="GtkAlignment" id="alignment1">
+		  <property name="visible">True</property>
+		  <property name="xalign">0.5</property>
+		  <property name="yalign">0.5</property>
+		  <property name="xscale">0</property>
+		  <property name="yscale">0</property>
+		  <property name="top_padding">0</property>
+		  <property name="bottom_padding">0</property>
+		  <property name="left_padding">0</property>
+		  <property name="right_padding">0</property>
+
+		  <child>
+		    <widget class="GtkHBox" id="hbox2">
+		      <property name="visible">True</property>
+		      <property name="homogeneous">False</property>
+		      <property name="spacing">2</property>
+
+		      <child>
+			<widget class="GtkImage" id="image1">
+			  <property name="visible">True</property>
+			  <property name="stock">gtk-ok</property>
+			  <property name="icon_size">4</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">False</property>
+			  <property name="fill">False</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="label5">
+			  <property name="visible">True</property>
+			  <property name="can_default">True</property>
+			  <property name="has_default">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="has_focus">True</property>
+			  <property name="label" translatable="yes">Purchase</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">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>
+	      </child>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	      <property name="pack_type">GTK_PACK_END</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkButton" id="button2">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-cancel</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <signal name="clicked" handler="rb_magnatune_cancel_button_clicked_cb" last_modification_time="Mon, 26 Jun 2006 22:24:31 GMT"/>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	      <property name="pack_type">GTK_PACK_END</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
--- /dev/null	2006-05-23 00:25:23.000000000 +1000
+++ plugins/magnatune/magnatune-prefs.glade	2006-06-29 03:41:16.000000000 +1000
@@ -0,0 +1,697 @@
+<?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="GtkWindow" id="preferences">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes"></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">False</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="magnatune_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="GtkVBox" id="vbox2">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">6</property>
+
+	  <child>
+	    <widget class="GtkLabel" id="magnatune_label">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Magnatune Information</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="GtkHBox" id="hbox14">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<widget class="GtkLabel" id="label20">
+		  <property name="visible">True</property>
+		  <property name="label"></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">8</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="GtkVBox" id="vbox13">
+		  <property name="visible">True</property>
+		  <property name="homogeneous">False</property>
+		  <property name="spacing">6</property>
+
+		  <child>
+		    <widget class="GtkTable" id="table1">
+		      <property name="visible">True</property>
+		      <property name="n_rows">4</property>
+		      <property name="n_columns">2</property>
+		      <property name="homogeneous">False</property>
+		      <property name="row_spacing">6</property>
+		      <property name="column_spacing">12</property>
+
+		      <child>
+			<widget class="GtkLabel" id="username_label">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">_Name:</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</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="mnemonic_widget">name_entry</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="GtkEntry" id="name_entry">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="editable">True</property>
+			  <property name="visibility">True</property>
+			  <property name="max_length">0</property>
+			  <property name="text" translatable="yes"></property>
+			  <property name="has_frame">True</property>
+			  <property name="invisible_char">*</property>
+			  <property name="activates_default">False</property>
+			  <signal name="changed" handler="rb_magnatune_name_entry_changed_cb" last_modification_time="Mon, 26 Jun 2006 19:58:32 GMT"/>
+			  <signal name="activate" handler="rb_magnatune_name_entry_activate_cb" last_modification_time="Mon, 26 Jun 2006 19:58:37 GMT"/>
+			</widget>
+			<packing>
+			  <property name="left_attach">1</property>
+			  <property name="right_attach">2</property>
+			  <property name="top_attach">0</property>
+			  <property name="bottom_attach">1</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkEntry" id="email_entry">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="editable">True</property>
+			  <property name="visibility">True</property>
+			  <property name="max_length">0</property>
+			  <property name="text" translatable="yes"></property>
+			  <property name="has_frame">True</property>
+			  <property name="invisible_char">*</property>
+			  <property name="activates_default">False</property>
+			  <signal name="changed" handler="rb_magnatune_email_entry_changed_cb" last_modification_time="Mon, 26 Jun 2006 19:58:51 GMT"/>
+			  <signal name="activate" handler="rb_magnatune_email_entry_activate_cb" last_modification_time="Mon, 26 Jun 2006 19:58:57 GMT"/>
+			</widget>
+			<packing>
+			  <property name="left_attach">1</property>
+			  <property name="right_attach">2</property>
+			  <property name="top_attach">1</property>
+			  <property name="bottom_attach">2</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="password_label">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">_Email:</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</property>
+			  <property name="yalign">0.5</property>
+			  <property name="xpad">0</property>
+			  <property name="ypad">0</property>
+			  <property name="mnemonic_widget">email_entry</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="cc_label">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">_Credit Card:</property>
+			  <property name="use_underline">True</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="mnemonic_widget">cc_entry</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="GtkEntry" id="cc_entry">
+			  <property name="visible">True</property>
+			  <property name="can_focus">True</property>
+			  <property name="editable">True</property>
+			  <property name="visibility">True</property>
+			  <property name="max_length">0</property>
+			  <property name="text" translatable="yes"></property>
+			  <property name="has_frame">True</property>
+			  <property name="invisible_char">●</property>
+			  <property name="activates_default">False</property>
+			  <signal name="changed" handler="rb_magnatune_cc_entry_changed_cb" last_modification_time="Mon, 26 Jun 2006 19:55:57 GMT"/>
+			  <signal name="activate" handler="rb_magnatune_cc_entry_activate_cb" last_modification_time="Mon, 26 Jun 2006 19:56:16 GMT"/>
+			</widget>
+			<packing>
+			  <property name="left_attach">1</property>
+			  <property name="right_attach">2</property>
+			  <property name="top_attach">2</property>
+			  <property name="bottom_attach">3</property>
+			  <property name="y_options"></property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkHBox" id="hbox20">
+			  <property name="visible">True</property>
+			  <property name="homogeneous">False</property>
+			  <property name="spacing">0</property>
+
+			  <child>
+			    <widget class="GtkLabel" id="mm_label">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">mm:</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">8</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="GtkEntry" id="mm_entry">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">True</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">2</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">●</property>
+			      <property name="activates_default">False</property>
+			      <signal name="changed" handler="rb_magnatune_mm_entry_changed_cb" last_modification_time="Mon, 26 Jun 2006 19:56:50 GMT"/>
+			      <signal name="activate" handler="rb_magnatune_mm_entry_activate_cb" last_modification_time="Mon, 26 Jun 2006 19:57:03 GMT"/>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">False</property>
+			      <property name="fill">True</property>
+			    </packing>
+			  </child>
+
+			  <child>
+			    <widget class="GtkLabel" id="yy_label">
+			      <property name="visible">True</property>
+			      <property name="label" translatable="yes">yy:</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">8</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="GtkEntry" id="yy_entry">
+			      <property name="visible">True</property>
+			      <property name="can_focus">True</property>
+			      <property name="editable">True</property>
+			      <property name="visibility">True</property>
+			      <property name="max_length">2</property>
+			      <property name="text" translatable="yes"></property>
+			      <property name="has_frame">True</property>
+			      <property name="invisible_char">●</property>
+			      <property name="activates_default">False</property>
+			      <signal name="changed" handler="rb_magnatune_yy_entry_changed_cb" last_modification_time="Mon, 26 Jun 2006 19:57:17 GMT"/>
+			      <signal name="activate" handler="rb_magnatune_yy_entry_activate_cb" last_modification_time="Mon, 26 Jun 2006 19:57:27 GMT"/>
+			    </widget>
+			    <packing>
+			      <property name="padding">0</property>
+			      <property name="expand">True</property>
+			      <property name="fill">True</property>
+			    </packing>
+			  </child>
+			</widget>
+			<packing>
+			  <property name="left_attach">1</property>
+			  <property name="right_attach">2</property>
+			  <property name="top_attach">3</property>
+			  <property name="bottom_attach">4</property>
+			  <property name="x_options">fill</property>
+			</packing>
+		      </child>
+
+		      <child>
+			<widget class="GtkLabel" id="exp_label">
+			  <property name="visible">True</property>
+			  <property name="label" translatable="yes">E_xpiry:</property>
+			  <property name="use_underline">True</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="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>
+		    </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>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHBox" id="hbox22">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <widget class="GtkLabel" id="pay_label">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">Default Amount to Pay:</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">8</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="GtkComboBox" id="pay_combobox">
+	      <property name="visible">True</property>
+	      <property name="items" translatable="yes">$5
+$6
+$7
+$8 (typical)
+$9
+$10 (better than average)
+$11
+$12 (generous)
+$13
+$14
+$15 (VERY generous!)
+$16
+$17
+$18 (We love you!)</property>
+	      <property name="add_tearoffs">False</property>
+	      <property name="focus_on_click">True</property>
+	      <signal name="changed" handler="rb_magnatune_pay_combobox_changed_cb" last_modification_time="Mon, 26 Jun 2006 20:12:55 GMT"/>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">True</property>
+	    </packing>
+	  </child>
+
+	  <child>
+	    <widget class="GtkLabel" id="label56">
+	      <property name="visible">True</property>
+	      <property name="label" translatable="yes">(US Dollars)</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">8</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>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">True</property>
+	  <property name="fill">True</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">Preferred Audio Format:</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">8</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="GtkComboBox" id="audio_combobox">
+	      <property name="visible">True</property>
+	      <property name="items" translatable="yes">Ogg Vorbis
+FLAC
+WAV
+VBR MP3
+128K MP3</property>
+	      <property name="add_tearoffs">False</property>
+	      <property name="focus_on_click">True</property>
+	      <signal name="changed" handler="rb_magnatune_audio_combobox_changed_cb" last_modification_time="Mon, 26 Jun 2006 20:06:22 GMT"/>
+	    </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">True</property>
+	  <property name="fill">True</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkVBox" id="vbox14">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <widget class="GtkHBox" id="hbox15">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<widget class="GtkLabel" id="label21">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Find out about Magnatune at </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">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="magnatune_link">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="url">http://www.magnatune.com/</property>
+		  <property name="text" translatable="yes">http://www.magnatune.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>
+
+	  <child>
+	    <widget class="GtkHBox" id="hbox17">
+	      <property name="visible">True</property>
+	      <property name="homogeneous">False</property>
+	      <property name="spacing">0</property>
+
+	      <child>
+		<widget class="GtkLabel" id="label27">
+		  <property name="visible">True</property>
+		  <property name="label" translatable="yes">Redownload purchased music at </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">0</property>
+		  <property name="ypad">0</property>
+		  <property name="mnemonic_widget">redownload_link</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="redownload_link">
+		  <property name="visible">True</property>
+		  <property name="can_focus">True</property>
+		  <property name="url">http://www.magnatune.com/info/redownload</property>
+		  <property name="text" translatable="yes">http://www.magnatune.com/info/redownload</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>
--- /dev/null	2006-05-23 00:25:23.000000000 +1000
+++ plugins/magnatune/magnatune-download.glade	2006-06-29 05:16:16.000000000 +1000
@@ -0,0 +1,115 @@
+<?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="download_window">
+  <property name="title" translatable="yes">Download Progress</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_CENTER</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>
+  <signal name="delete_event" handler="on_download_window_delete_event" last_modification_time="Wed, 28 Jun 2006 18:52:32 GMT"/>
+
+  <child>
+    <widget class="GtkVBox" id="vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">8</property>
+
+      <child>
+	<widget class="GtkLabel" id="info_label">
+	  <property name="visible">True</property>
+	  <property name="label" translatable="yes">An email has been sent with download information in case
+you need to re-download this album in the future.</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.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="GtkProgressBar" id="download_pbar">
+	  <property name="visible">True</property>
+	  <property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property>
+	  <property name="fraction">0</property>
+	  <property name="pulse_step">0.10000000149</property>
+	  <property name="text" translatable="yes">0%</property>
+	  <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+
+      <child>
+	<widget class="GtkHSeparator" id="hseparator1">
+	  <property name="visible">True</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="hbox1">
+	  <property name="visible">True</property>
+	  <property name="homogeneous">False</property>
+	  <property name="spacing">0</property>
+
+	  <child>
+	    <widget class="GtkButton" id="cancel_button">
+	      <property name="visible">True</property>
+	      <property name="can_focus">True</property>
+	      <property name="label">gtk-cancel</property>
+	      <property name="use_stock">True</property>
+	      <property name="relief">GTK_RELIEF_NORMAL</property>
+	      <property name="focus_on_click">True</property>
+	      <signal name="clicked" handler="rb_magnatune_cancel_button_clicked_cb" last_modification_time="Wed, 28 Jun 2006 18:41:24 GMT"/>
+	    </widget>
+	    <packing>
+	      <property name="padding">0</property>
+	      <property name="expand">False</property>
+	      <property name="fill">False</property>
+	      <property name="pack_type">GTK_PACK_END</property>
+	    </packing>
+	  </child>
+	</widget>
+	<packing>
+	  <property name="padding">0</property>
+	  <property name="expand">False</property>
+	  <property name="fill">False</property>
+	</packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
--- /dev/null	2006-05-23 00:25:23.000000000 +1000
+++ plugins/magnatune/magnatune/TrackListHandler.py	2006-06-30 14:10:39.000000000 +1000
@@ -0,0 +1,49 @@
+import rhythmdb
+import xml.sax, xml.sax.handler
+import datetime
+
+class TrackListHandler(xml.sax.handler.ContentHandler):
+	
+	def __init__(self, db, entry_type, sku_dict):
+		xml.sax.handler.ContentHandler.__init__(self)
+		self._track = {} # temporary dictionary for track info
+		self._db = db
+		self._entry_type = entry_type
+		self._sku_dict = sku_dict
+	
+	def startElement(self, name, attrs):
+		self._text = ""
+	
+	def endElement(self, name):
+		if name == "Track":
+			try:
+				# add the track to the source
+				entry = self._db.entry_new(self._entry_type, self._track['url'])
+				if entry == None:
+					print "duplicate entry:", self._track['url']
+					return
+
+				date = datetime.date(int(self._track['launchdate'][0:4]), 1, 1).toordinal() # year is sometimes 0, so we use launchdate
+				
+				self._db.entry_set_uninserted(entry, rhythmdb.PROP_ARTIST, self._track['artist'])
+				self._db.entry_set_uninserted(entry, rhythmdb.PROP_ALBUM, self._track['albumname'])
+				self._db.entry_set_uninserted(entry, rhythmdb.PROP_TITLE, self._track['trackname'])
+				self._db.entry_set_uninserted(entry, rhythmdb.PROP_TRACK_NUMBER, int(self._track['tracknum']))
+				self._db.entry_set_uninserted(entry, rhythmdb.PROP_DATE, date)
+				self._db.entry_set_uninserted(entry, rhythmdb.PROP_GENRE, self._track['mp3genre'])
+				self._db.entry_set_uninserted(entry, rhythmdb.PROP_DURATION, int(self._track['seconds']))
+				self._sku_dict[self._track['url']] = self._track['albumsku']
+				
+				self._db.commit()
+			except Exception,e: # This happens on duplicate uris being added
+				print "Couldn't add %s - %s" % (self._track['artist'], self._track['trackname']) # TODO: This should be printed to debug
+				print e
+			
+			self._track = {}
+		elif name == "AllSongs":
+			pass # end of the file
+		else:
+			self._track[name] = self._text
+	
+	def characters(self, content):
+		self._text = self._text + content
--- /dev/null	2006-05-23 00:25:23.000000000 +1000
+++ plugins/magnatune/magnatune/BuyAlbumHandler.py	2006-06-29 15:31:20.000000000 +1000
@@ -0,0 +1,35 @@
+import gnomevfs
+import xml.sax, xml.sax.handler
+
+class BuyAlbumHandler(xml.sax.handler.ContentHandler): # Class to download the track, etc.
+	
+	format_map =	{
+			'ogg'		:	'URL_OGGZIP',
+			'flac'		:	'URL_FLACZIP',
+			'wav'		:	'URL_WAVZIP',
+			'mp3-cbr'	:	'URL_128KMP3ZIP',
+			'mp3-vbr'	:	'URL_VBRZIP'
+			}
+	
+	def __init__(self, format):
+		xml.sax.handler.ContentHandler.__init__(self)
+		self._format_tag = self.format_map[format] # format of audio to download
+	
+	def startElement(self, name, attrs):
+		self._text = ""
+	
+	def endElement(self, name):
+		if name == "ERROR": # Something went wrong. Display error message to user.
+			raise MagnatunePurchaseError(self._text)
+		elif name == "DL_USERNAME":
+			self.username = self._text
+		elif name == "DL_PASSWORD":
+			self.password = self._text
+		elif name == self._format_tag:
+			self.url = self._text
+	
+	def characters(self, content):
+		self._text = self._text + content
+
+class MagnatunePurchaseError(Exception):
+	pass
--- /dev/null	2006-05-23 00:25:23.000000000 +1000
+++ plugins/magnatune/magnatune/MagnatuneSource.py	2006-06-30 15:00:02.000000000 +1000
@@ -0,0 +1,14 @@
+import rb, rhythmdb
+import gobject
+
+
+class MagnatuneSource(rb.BrowserSource):
+	def __init__(self):
+		rb.Source.__init__(self)
+
+	def do_impl_show_entry_popup(self):
+		self.show_source_popup ("/MagnatuneSourceViewPopup")
+
+gobject.type_register(MagnatuneSource)
+
+
--- /dev/null	2006-05-23 00:25:23.000000000 +1000
+++ plugins/magnatune/magnatune/__init__.py	2006-06-30 15:00:03.000000000 +1000
@@ -0,0 +1,519 @@
+import rhythmdb, rb
+import gobject
+import gtk, gtk.glade
+import gconf, gnomevfs, gnome
+
+import urllib
+import zipfile
+import sys, os.path
+import xml
+
+from BuyAlbumHandler import BuyAlbumHandler
+from MagnatuneSource import MagnatuneSource
+from TrackListHandler import TrackListHandler
+
+magnatune_partner_id = "zimmerman"
+
+user_dir = gnome.user_dir_get()
+magnatune_dir = user_dir + "rhythmbox/magnatune/"
+magnatune_dir_uri = gnomevfs.URI(magnatune_dir)
+magnatune_song_info_uri = gnomevfs.URI("http://magnatune.com/info/song_info.xml")
+local_song_info_uri = gnomevfs.URI(magnatune_dir + "song_info.xml")
+lc_uri = gnomevfs.URI(magnatune_dir + "info_last_changed")
+file_locn = sys.prefix + "/share/rhythmbox/glade"
+
+sku_dict = {}
+
+popup_ui = """
+<ui>
+  <popup name="MagnatuneSourceViewPopup">
+    <menuitem name="AddToQueueLibraryPopup" action="AddToQueue"/>
+    <menuitem name="MagnatunePurchaseAlbum" action="MagnatunePurchase"/>
+    <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 Magnatune(rb.Plugin):
+	
+	info_file = None
+	remote_info_file = None
+	configure_dialog = None
+	purchase_filesize = 0
+	
+	#
+	# Core methods
+	#
+	
+	def __init__(self):
+		rb.Plugin.__init__(self)
+		self.configure_callback_dic = {
+				"rb_magnatune_name_entry_changed_cb" : self.name_entry_cb,
+				"rb_magnatune_name_entry_activate_cb" : self.name_entry_cb,
+				"rb_magnatune_email_entry_changed_cb" : self.email_entry_cb,
+				"rb_magnatune_email_entry_activate_cb" : self.email_entry_cb,
+				"rb_magnatune_cc_entry_changed_cb" : self.cc_entry_cb,
+				"rb_magnatune_cc_entry_activate_cb" : self.cc_entry_cb,
+				"rb_magnatune_mm_entry_changed_cb" : self.mm_entry_cb,
+				"rb_magnatune_mm_entry_activate_cb" : self.mm_entry_cb,
+				"rb_magnatune_yy_entry_changed_cb" : self.yy_entry_cb,
+				"rb_magnatune_yy_entry_activate_cb" : self.yy_entry_cb,
+				"rb_magnatune_pay_combobox_changed_cb" : self.pay_combobox_cb,
+				"rb_magnatune_audio_combobox_changed_cb" : self.audio_combobox_cb
+				}
+		
+	def activate(self, shell):
+		self.shell = shell # so buy_track can update the progress bar
+		self.db = shell.get_property("db")
+		self.entry_type = rhythmdb.entry_register_type("MagnatuneEntryType")
+		icon = gtk.gdk.pixbuf_new_from_xpm_data(magnatune_logo_xpm) # Include a flashy Magnatune logo for the source
+		self.source = gobject.new (MagnatuneSource, shell=shell, name=_("Magnatune"), entry_type=self.entry_type, icon=icon)
+		shell.register_entry_type_for_source(self.source, self.entry_type)
+		self.source.info_screen = gtk.Label()
+		
+		ev = self.source.get_entry_view()
+		shell.append_source(self.source, None) # Add the source to the list
+		
+		manager = shell.get_player().get_property('ui-manager')
+		action = gtk.Action('MagnatunePurchase', _('Purchase Album'),
+				_("Purchase this album from Magnatune"),
+				'gnome-mime-audio')
+		action.connect('activate', self.confirm_track_purchase)
+		self.action_group = gtk.ActionGroup('MagnatunePluginActions')
+		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()
+		
+		self.parser = xml.sax.make_parser()
+		self.parser.setContentHandler(TrackListHandler(self.db, self.entry_type, sku_dict))
+		if check_info():
+			gobject.idle_add(self.idle_download_info)
+		else:
+			gobject.idle_add(self.idle_load_info)
+		gobject.timeout_add(6 * 60 * 60 * 1000, self.check_info_updates) # every 6 hours.
+	
+	def deactivate(self, shell):
+		# FIXME: should remove the ui stuff here
+		self.db.entry_delete_by_type(self.entry_type)
+		self.db.commit()
+		self.source.delete_thyself()
+		self.source = None
+	
+	def create_configure_dialog(self):
+		client = gconf.client_get_default()
+		
+		if self.configure_dialog == None:
+			self.configure_dialog_xml = gtk.glade.XML(os.path.join(file_locn, "magnatune-prefs.glade"), root="magnatune_vbox")
+			self.configure_dialog_xml.signal_autoconnect(self.configure_callback_dic)
+			self.configure_dialog = gtk.Dialog(title="Magnatune Preferences", flags=gtk.DIALOG_DESTROY_WITH_PARENT,
+							buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
+			
+			self.configure_dialog.set_border_width(5)
+			self.configure_dialog.vbox.set_spacing(2)
+			self.configure_dialog.set_has_separator(False)
+			self.configure_dialog.connect("response", self.prefs_response_cb)
+			self.configure_dialog.hide_on_delete()
+			self.configure_dialog.vbox.pack_start(self.configure_dialog_xml.get_widget("magnatune_vbox"))
+			
+			self.name_entry = self.configure_dialog_xml.get_widget("name_entry")
+			self.email_entry = self.configure_dialog_xml.get_widget("email_entry")
+			self.cc_entry = self.configure_dialog_xml.get_widget("cc_entry")
+			self.mm_entry = self.configure_dialog_xml.get_widget("mm_entry")
+			self.yy_entry = self.configure_dialog_xml.get_widget("yy_entry")
+			self.pay_combobox = self.configure_dialog_xml.get_widget("pay_combobox")
+			self.audio_combobox = self.configure_dialog_xml.get_widget("audio_combobox")
+		
+		self.set_pref_values()
+		self.configure_dialog.show()
+		return self.configure_dialog
+	
+	
+	#
+	# Callback/helper functions
+	#
+	
+	def confirm_track_purchase(self, action):
+		callbacks = {
+			"rb_magnatune_purchase_button_clicked_cb" : self.purchase_clicked,
+			"rb_magnatune_cancel_button_clicked_cb" : self.cancel_clicked
+			}
+		tracks = self.source.get_entry_view().get_selected_entries()
+
+		self.sku = sku_dict[self.db.entry_get(tracks[0], rhythmdb.PROP_LOCATION)]
+		self.artist = self.db.entry_get(tracks[0], rhythmdb.PROP_ARTIST)
+		self.album = self.db.entry_get(tracks[0], rhythmdb.PROP_ALBUM)
+
+
+		client = gconf.client_get_default()
+		self.pay = client.get_int("/apps/rhythmbox/plugins/magnatune/pay")
+		self.audio = client.get_int("/apps/rhythmbox/plugins/magnatune/audio")
+		
+		self.confirm_window = gtk.glade.XML(os.path.join(file_locn, "magnatune-confirm.glade"))
+		self.confirm_window.signal_autoconnect(callbacks)
+		self.confirm_window.get_widget("pay_combobox").set_active(self.pay)
+		self.confirm_window.get_widget("audio_combobox").set_active(self.audio)
+		self.confirm_window.get_widget("info_label").set_text(_("You are about to purchase the album '%s' by '%s'.") % (self.album, self.artist))
+		self.confirm_window.get_widget("confirm_window").show()
+	
+	def check_info_updates(self): # TODO: if possible, make it so that the updated file is downloaded first, then the entries are switched
+		if check_info():
+			self.db.entry_delete_by_type(self.entry_type)
+			self.db.commit()
+			gobject.idle_add(self.idle_download_info)
+		return True
+	
+	def idle_load_info(self):
+		if self.info_file == None:
+			self.info_file = gnomevfs.open(local_song_info_uri)
+		try:
+			self.parser.feed(self.info_file.read(128 * 1024))
+			return True
+		except gnomevfs.EOFError:
+			self.info_file.close()
+			self.info_file = None
+			self.source.info_screen.hide()
+			self.source.info_screen.destroy()
+			self.source.info_screen = gtk.Label()
+			self.source.get_entry_view().show()
+			return False
+	
+	def idle_download_info(self):
+		if self.info_file == None:
+			self.remote_info_file = gnomevfs.open(magnatune_song_info_uri)
+			self.info_file_length = self.remote_info_file.get_file_info().size
+			self.downloaded = 0
+			self.info_file = gnomevfs.create(local_song_info_uri, open_mode=gnomevfs.OPEN_WRITE)
+			self.source.get_entry_view().hide()
+			self.source.info_screen = gtk.Label()
+			self.source.info_screen.set_markup(info_loading)
+			self.source.pack_start(self.source.info_screen)
+			self.source.info_screen.show()
+		try:
+			data = self.remote_info_file.read(64 * 1024)
+			self.info_file.write(data)
+			self.downloaded += len(data)
+			progress = int(self.downloaded / float(self.info_file_length) * 100)
+			self.source.info_screen.set_markup(info_loading + str(progress) + "%")
+			return True
+		except gnomevfs.EOFError:
+			self.remote_info_file.close()
+			self.info_file.close()
+			self.remote_info_file = None
+			self.info_file = None
+			gobject.idle_add(self.idle_load_info)
+			return False
+	
+	#
+	# Purchasing Code
+	#
+	
+	def buy_track(self, sku, amount, cc, name, email, format): # http://magnatune.com/info/api#purchase
+		client = gconf.client_get_default()
+		url = "https://magnatune.com/buy/buy_dl_cc_xml?"
+		url = url + urllib.urlencode({
+						'id':	magnatune_partner_id,
+						'sku':	sku,
+						'amount': amount,
+						'cc':	cc['number'],
+						'yy':	cc['year'],
+						'mm':	cc['month'],
+						'name': name,
+						'email':email
+					})
+		
+		buy_album_handler = BuyAlbumHandler(format) # so we can get the url and auth info
+		parser = xml.sax.make_parser()
+		parser.setContentHandler(buy_album_handler)
+		data = gnomevfs.read_entire_file(url).replace("<br>", "") # get rid of that single pesky <br> tag
+		parser.feed(data)
+		audio_dl_uri = gnomevfs.URI(buy_album_handler.url)
+		audio_dl_uri = gnomevfs.URI(buy_album_handler.url[0:buy_album_handler.url.rfind("/") + 1] + urllib.quote(audio_dl_uri.short_name))
+		audio_dl_uri.user_name = str(buy_album_handler.username) # URI objects don't like unicode strings
+		audio_dl_uri.password = str(buy_album_handler.password)
+		
+		library_location = client.get_list("/apps/rhythmbox/library_locations", gconf.VALUE_STRING)[0] # Just use the first library location
+		to_file_uri = gnomevfs.URI(library_location + "/" + audio_dl_uri.short_name)
+		
+		dl_file = gnomevfs.open(audio_dl_uri)
+		to_file = create_if_needed(to_file_uri, gnomevfs.OPEN_WRITE)
+		gobject.idle_add(self.transfer_album, dl_file, to_file, to_file_uri, library_location)
+	
+	def transfer_album(self, dl_file, to_file, to_file_uri, library_location):
+	# Download the album and unzip it into the library
+		try:
+			if self.purchase_filesize == 0:
+				callbacks = {"rb_magnatune_cancel_button_clicked_cb" : self.dl_cancel_clicked,
+					     "on_download_window_delete_event"	:	self.close_clicked}
+				self.purchase_downloaded = 0
+				self.purchase_filesize = dl_file.get_file_info().size
+				
+				self.progress_dialog = gtk.glade.XML(os.path.join(file_locn, "magnatune-download.glade"))
+				self.progress_dialog.signal_autoconnect(callbacks)
+				self.cancelled = False
+				self.progress_dialog.get_widget("download_window").show()
+			
+			if self.cancelled:
+				dl_file.close()
+				to_file.close()
+				gnomevfs.unlink(to_file_uri)
+				self.progress_dialog.get_widget("download_window").destroy()
+				self.progress_dialog = None
+				self.purchase_filesize = 0
+				return False
+			
+			data = dl_file.read(64 * 1024)
+			to_file.write(data)
+			self.purchase_downloaded += len(data)
+			purchase_fraction = self.purchase_downloaded / float(self.purchase_filesize)
+			self.progress_dialog.get_widget("download_pbar").set_fraction(purchase_fraction)
+			self.progress_dialog.get_widget("download_pbar").set_text(str(int(purchase_fraction * 100)) + "%")
+			return True
+		except gnomevfs.EOFError:
+			dl_file.close()
+			to_file.close()
+			album = zipfile.ZipFile(to_file_uri.path)
+			for track in album.namelist():
+				track_uri = gnomevfs.URI(library_location + "/" + track)
+				out = create_if_needed(track_uri, gnomevfs.OPEN_WRITE)
+				out.write(album.read(track))
+				out.close()
+			album.close()
+			gnomevfs.unlink(to_file_uri)
+			self.progress_dialog.get_widget("download_window").destroy()
+			self.progress_dialog = None
+			self.purchase_filesize = 0
+			self.db.add_uri("file://" + urllib.quote(track_uri.dirname))
+			return False
+	
+	def close_clicked(self, dialog, response):
+		self.cancelled = True
+	def dl_cancel_clicked(self, dialog):
+		self.cancelled = True
+	
+	#
+	# Preferences window callbacks
+	#
+	
+	def name_entry_cb(self, widget):
+		client = gconf.client_get_default()
+		client.set_string("/apps/rhythmbox/plugins/magnatune/name", widget.get_text())
+	def email_entry_cb(self, widget):
+		client = gconf.client_get_default()
+		client.set_string("/apps/rhythmbox/plugins/magnatune/email", widget.get_text())
+	def cc_entry_cb(self, widget):
+		client = gconf.client_get_default()
+		client.set_string("/apps/rhythmbox/plugins/magnatune/cc", widget.get_text())
+	def mm_entry_cb(self, widget):
+		client = gconf.client_get_default()
+		client.set_string("/apps/rhythmbox/plugins/magnatune/mm", widget.get_text())
+	def yy_entry_cb(self, widget):
+		client = gconf.client_get_default()
+		client.set_string("/apps/rhythmbox/plugins/magnatune/yy", widget.get_text())
+	def pay_combobox_cb(self, widget):
+		client = gconf.client_get_default()
+		client.set_int("/apps/rhythmbox/plugins/magnatune/pay", widget.get_active())
+	def audio_combobox_cb(self, widget):
+		client = gconf.client_get_default()
+		client.set_int("/apps/rhythmbox/plugins/magnatune/audio", widget.get_active())
+	def prefs_response_cb(self, dialog, response):
+		dialog.hide()
+	
+	def set_pref_values(self):
+		client = gconf.client_get_default()
+		
+		if client.get_string("/apps/rhythmbox/plugins/magnatune/name") == None:
+			client.set_string("/apps/rhythmbox/plugins/magnatune/name", "")
+			client.set_string("/apps/rhythmbox/plugins/magnatune/email", "")
+			client.set_string("/apps/rhythmbox/plugins/magnatune/cc", "")
+			client.set_string("/apps/rhythmbox/plugins/magnatune/mm", "")
+			client.set_string("/apps/rhythmbox/plugins/magnatune/yy", "")
+			client.set_int("/apps/rhythmbox/plugins/magnatune/pay", 3)
+			client.set_int("/apps/rhythmbox/plugins/magnatune/audio", 0)
+		
+		self.name_entry.set_text(client.get_string("/apps/rhythmbox/plugins/magnatune/name"))
+		self.email_entry.set_text(client.get_string("/apps/rhythmbox/plugins/magnatune/email"))
+		self.cc_entry.set_text(client.get_string("/apps/rhythmbox/plugins/magnatune/cc"))
+		self.mm_entry.set_text(client.get_string("/apps/rhythmbox/plugins/magnatune/mm"))
+		self.yy_entry.set_text(client.get_string("/apps/rhythmbox/plugins/magnatune/yy"))
+		self.pay_combobox.set_active(client.get_int("/apps/rhythmbox/plugins/magnatune/pay"))
+		self.audio_combobox.set_active(client.get_int("/apps/rhythmbox/plugins/magnatune/audio"))
+	
+	def purchase_clicked(self, widget):
+		client = gconf.client_get_default()
+		format_list = ['ogg', 'flac', 'wav', 'mp3-vbr', 'mp3-cbr']
+		cc = {}
+		cc['number'] = client.get_string("/apps/rhythmbox/plugins/magnatune/cc")
+		cc['year'] = client.get_string("/apps/rhythmbox/plugins/magnatune/yy")
+		cc['month'] = client.get_string("/apps/rhythmbox/plugins/magnatune/mm")
+		name = client.get_string("/apps/rhythmbox/plugins/magnatune/name")
+		email = client.get_string("/apps/rhythmbox/plugins/magnatune/email")
+		
+		amount = self.confirm_window.get_widget("pay_combobox").get_active() + 5
+		format = format_list[self.confirm_window.get_widget("audio_combobox").get_active()]
+		self.confirm_window.get_widget("confirm_window").destroy()
+		dlg = gtk.Dialog(title="Connecting: Please Wait")
+		lbl = gtk.Label("Connecting to the Magnatune server: please wait...")
+		dlg.vbox.pack_start(lbl)
+		lbl.show()
+		dlg.show()
+		dlg.set_modal(True)
+		try:
+			self.buy_track(self.sku, amount, cc, name, email, format)
+			dlg.destroy()
+		except MagnatuneError, e:
+			dlg.destroy()
+			error_dlg = gtk.Dialog(title="Error", flags=gtk.DIALOG_DESTROY_WITH_PARENT, buttons=(gtk.STOCK_OK, gtk.RESPONSE_OK))
+			label = gtk.Label(_("An error occurred while trying to purchase the album.\nThe Magnatune server returned:\n%s") % str(e))
+			error_dlg.vbox.pack_start(label)
+			label.set_selectable(True)
+			label.show()
+			error_dlg.connect("response", self.ok_clicked)
+			error_dlg.show()
+	
+	def ok_clicked(self, dialog, response):
+		dialog.destroy()
+	
+	def cancel_clicked(self, widget):
+		self.confirm_window.get_widget("confirm_window").destroy()
+
+
+
+
+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)
+
+
+
+################################################
+# Methods for downloading the song info        #
+################################################
+
+def check_info():
+# returns whether or not info has changed
+	if not gnomevfs.exists(magnatune_dir_uri):
+		gnomevfs.make_directory(magnatune_dir_uri, 0755)
+	if not gnomevfs.exists(lc_uri):
+		t = gnomevfs.create(lc_uri, open_mode=gnomevfs.OPEN_WRITE)
+		t.write("never") # there needs to be something in the file, otherwise it throws an exception when read from
+		t.close()
+	modified = str(gnomevfs.get_file_info(magnatune_song_info_uri).mtime)
+	lc_file = gnomevfs.open(lc_uri)
+	last_changed = lc_file.read(100) # file should be less than 100 chars
+	lc_file.close()
+	if not last_changed.strip() == modified.strip():
+		lc_file = gnomevfs.open(lc_uri, open_mode=gnomevfs.OPEN_WRITE)
+		lc_file.write(modified)
+		lc_file.close()
+		return True
+	return False
+
+
+
+################################################
+# Magnatune Logo.                              #
+################################################
+
+# (converted from http://www.magnatune.com/favicon.ico)
+
+magnatune_logo_xpm = [
+"32 32 4 1",
+" 	c None", #Original colours:
+".	c None", #FFFFFF
+"+	c #303030", #C0C0C0 
+"@	c #000000", #808080
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"............++@@@@++............",
+"..........+@@@@@@@@@@+..........",
+".........+@@@+....+@@@+.........",
+"........+@@+...++...+@@+........",
+".......+@@+....@@....+@@+.......",
+".......@@+.....@@.....+@@.......",
+"......+@@......@@......@@+......",
+"......+@+......@@......+@+......",
+"......@@...@@..@@..@@...@@......",
+"......@@...@@+.@@.+@@...@@......",
+"......@@...@@+.@@.+@@...@@......",
+"......@@...@@+.@@.+@@...@@......",
+"......+@+..@@+.@@.+@@..+@+......",
+"......+@@..@@+.@@.+@@..@@+......",
+".......@@+.@@+.@@.+@@.+@@.......",
+".......+@@+.+..+...+.+@@+.......",
+"........+@@+........+@@+........",
+".........+@@@+....+@@@+.........",
+"..........+@@@@@@@@@@+..........",
+"............++@@@@++............",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................",
+"................................"
+]
+
+info_loading = _("""<b>Loading Magnatune Catalog</b>
+
+Magnatune is an online record label that is not evil. Some of their key attributes are:
+
+    * Free listening of all songs
+    * All albums and artists hand-picked
+    * Very simple user interface, quick to play music
+    * Radio stations and "genre mix" playlists allow background listening - can do work while listening to our music
+    * No need to "register" to listen or buy
+    * Smaller selection means easier to find good music
+    * Wide variety of genres, can fit any mood
+    * Our genres are hard to find in record stores and not on radio (though do appear on college radio)
+    * Downloads and CDs are both available (no other site on the internet sells both)
+    * Perfect quality downloads (CD copy) are available when you download (not inferior quality sound)
+    * No copy protection on the music (DRM) which allows playing music on any device (unlike iTunes/MSN/etc)
+    * Extensive biographical info about each musician, and artist photo -- feel a strong connection to the artist
+    * Full color, high quality cover art PDF available for most albums - easy to print
+    * Variable pricing scheme means you can pay as little as $5 for an album if you choose
+    * 50% of payment goes to artist (makes buyer feel good: they're helping the world)
+    * Not venture-capital backed big business
+    * Not part of the "evil" major label machine - for those that hate the music biz and want to help topple it
+    * Founder/owner runs it -- support a small business
+    * Low pressure environment - nothing flashing, no audio ads while listening to albums
+    * Music selection is unique to Magnatune, unlike most on-line stores that have more-or-less the same (gigantic) selection
+
+You can find more information at http://www.magnatune.com/
+
+
+""")
