13:17 < jimmac> kikidonk: would you have that last-exit patch handy? ;)
13:17 < kikidonk> oh yes
13:17 < jimmac> it's a sweet player
13:17 < kikidonk> http://raphael.slinckx.net/last-exit-save-song.patch
13:17 < kikidonk> against 0.2


diff -ru last-exit-0.2/data/glade/PlayerWindow.glade last-exit-0.2-mod/data/glade/PlayerWindow.glade
--- last-exit-0.2/data/glade/PlayerWindow.glade	2006-02-12 03:06:01.000000000 +0100
+++ last-exit-0.2-mod/data/glade/PlayerWindow.glade	2006-03-01 03:39:36.000000000 +0100
@@ -557,7 +557,32 @@
 			  <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="GtkButton" id="save_button">
+			  <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>
+
+			  <child>
+			    <widget class="GtkImage" id="image7">
+			      <property name="visible">True</property>
+			      <property name="stock">gtk-save-as</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>
+			  </child>
+			</widget>
+			<packing>
+			  <property name="padding">0</property>
+			  <property name="expand">False</property>
+			  <property name="fill">False</property>
 			</packing>
 		      </child>
 		    </widget>
Only in last-exit-0.2-mod/data/glade: PlayerWindow.glade.bak
Only in last-exit-0.2-mod/data/glade: PlayerWindow.gladep
Only in last-exit-0.2-mod/data/glade: PlayerWindow.gladep.bak
Only in last-exit-0.2-mod/liblast-exit: player-0.1-mod.c
Only in last-exit-0.2-mod/liblast-exit: player-0.2-mod.c
diff -ru last-exit-0.2/liblast-exit/player.c last-exit-0.2-mod/liblast-exit/player.c
--- last-exit-0.2/liblast-exit/player.c	2006-02-15 00:56:29.000000000 +0100
+++ last-exit-0.2-mod/liblast-exit/player.c	2006-03-01 04:53:39.000000000 +0100
@@ -21,15 +21,14 @@
 #include <config.h>
 #include <string.h>
 #include <math.h>
-
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <gst/gst.h>
 
-/*#include "last-fm.h"*/
 #include "player.h"
 
-/* #define USE_NEON 1 */
-/* #define USE_LAST_FM 1 */
-
 enum {
 	NEW_SONG,
 	ERROR,
@@ -38,6 +37,11 @@
 	
 struct _PlayerPrivate {
 	GstElement *play;
+	GstElement *multisink;
+	GstElement *src;
+	GstElement *volume;
+	
+	gchar *save_location;
 };
 
 static GObjectClass *parent_class;
@@ -81,6 +85,8 @@
 				       NULL, NULL,
 				       g_cclosure_marshal_VOID__STRING,
 				       G_TYPE_NONE, 1, G_TYPE_STRING);
+	
+	gst_init (NULL, NULL);
 }
 
 static void
@@ -124,6 +130,43 @@
 }
 
 static void
+change_dump_file (Player *player, gboolean create_new_file)
+{
+	gint fd;
+	gchar *temp_file_location = g_build_filename (g_get_home_dir (), ".lastfm.mp3", NULL);
+	
+	g_signal_emit_by_name (player->priv->multisink, "clear", fd);
+	if (player->priv->save_location != NULL)
+	{
+		/* We wanted to save the file */
+		fd = rename (temp_file_location, player->priv->save_location);
+		if (fd == -1)
+		{
+			perror("Error Occured while moving dump file to destination:");
+		}
+		g_free (player->priv->save_location);
+		player->priv->save_location = NULL;
+	}
+	
+	if (create_new_file)
+	{
+		fd = open (temp_file_location, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+		if (fd == -1)
+		{
+			perror("Error Occured while opening the file:");
+		}
+		
+		g_signal_emit_by_name (player->priv->multisink, "add", fd);
+	}
+	else
+	{
+		unlink (temp_file_location);
+	}
+	
+	g_free (temp_file_location);
+}
+
+static void
 post_new_song_message (Player *player)
 {
 	GstMessage *msg;
@@ -135,12 +178,23 @@
 
 	bus = gst_pipeline_get_bus (GST_PIPELINE (player->priv->play));
 	gst_bus_post (bus, msg);
+	
+	change_dump_file (player, TRUE);
 }
 
-static gboolean
-have_data_cb (GstPad *pad,
-	      GstBuffer *buffer,
-	      Player *player)
+static void
+client_removed (GstElement* multisink,
+                  gint fd,
+                  guint status,
+                  gpointer user_data)
+{
+	close(fd);
+}
+
+static void
+identity_handoff (GstElement *id,
+		  GstBuffer *buffer,
+		  Player *player)
 {
 	char *data = GST_BUFFER_DATA (buffer);
 	char *s;
@@ -154,51 +208,7 @@
 	s = memmem (data, GST_BUFFER_SIZE (buffer), sync, 4);
 	if (s != NULL) {
 		post_new_song_message (player);
-	} 
-#if 0
-	else if (req > 0) {
-		if (strncmp (data, sync + (4 - req), req) == 0) {
-			post_new_song_message (player);
-		}
-
-		// Reset req
-		req = 0;
-	} else {
-		guint len = GST_BUFFER_SIZE (buffer);
-		char *e = data + (len - 3);
-
-		// Is it even possible for the SYNC to get split over two
-		// different buffers? 
-
-		// Check if there is any of SYN in the last three chars
-		if (*(e + 2) == 'S') {
-			req = 3;
-		} else if ((*(e + 2) == 'Y') && (*(e + 1) == 'S')) {
-			req = 2;
-		} else if ((*(e + 2) == 'N') && (*(e + 1) == 'Y') && (*e == 'S')) {
-			req = 1;
-		} else {
-			req = 0;
-		}
 	}
-#endif
-
-	return TRUE;
-}
-
-static src_setup (GObject *object,
-		  GParamSpec *pspec,
-		  Player *player)
-{
-	GstElement *src;
-	GstPad *pad;
-
-	g_object_get (G_OBJECT (object),
-		      "source", &src,
-		      NULL);
-
-	pad = gst_element_get_pad (src, "src");
-	gst_pad_add_buffer_probe (pad, G_CALLBACK (have_data_cb), player);
 }
 
 static void
@@ -206,13 +216,27 @@
 		  char **error)
 {
 	PlayerPrivate *priv = player->priv;
-
-	gst_init (NULL, NULL);
-
-	priv->play = gst_element_factory_make ("playbin", "last-fm-player");
-	g_signal_connect (G_OBJECT (priv->play), "notify::source",
-			  G_CALLBACK (src_setup), player);
-
+	GstElement *bin;
+	GstElement *last_fm;
+	
+	priv->play = gst_pipeline_new ("last-fm-pipeline");
+	bin = gst_parse_bin_from_description (
+		"gnomevfssrc name=src ! identity name=last-fm ! tee name=t "
+		"t. ! queue ! mad ! audioconvert ! volume name=volume ! alsasink "
+		"t. ! queue ! multifdsink name=file sync-method=2",
+		TRUE,
+		NULL);
+	
+	last_fm = gst_bin_get_by_name (GST_BIN (bin), "last-fm");
+	g_signal_connect (G_OBJECT (last_fm), "handoff",
+			  G_CALLBACK (identity_handoff), player);
+			  
+	priv->src = gst_bin_get_by_name (GST_BIN (bin), "src");
+	priv->volume = gst_bin_get_by_name (GST_BIN (bin), "volume");
+	priv->multisink = gst_bin_get_by_name (GST_BIN (bin), "file");
+	g_signal_connect(priv->multisink, "client-removed", G_CALLBACK (client_removed), NULL);
+	
+	gst_bin_add (GST_BIN (priv->play), bin);
 	gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (priv->play)),
 			   bus_message_cb, player);
 }
@@ -255,14 +279,20 @@
 {
 	player_stop (player);
 
-	g_object_set (G_OBJECT (player->priv->play), 
-		      "uri", location, 
-		      NULL);
+	g_object_set (G_OBJECT (player->priv->src),
+		      "location", location, NULL);
 
 	return TRUE;
 }
 
 void
+player_set_save_location (Player *player,
+		     const char *location)
+{
+	player->priv->save_location = g_strdup (location);
+}
+
+void
 player_play (Player *player)
 {
 	gst_element_set_state (GST_ELEMENT (player->priv->play), GST_STATE_PLAYING);
@@ -272,6 +302,7 @@
 player_stop (Player *player)
 {
 	gst_element_set_state (GST_ELEMENT (player->priv->play), GST_STATE_READY);
+	change_dump_file (player, FALSE);
 }
 
 void
@@ -282,7 +313,7 @@
 
 	vol = CLAMP (volume, 0, 100) / 100.0;
 
-	g_object_set (G_OBJECT (player->priv->play),
+	g_object_set (G_OBJECT (player->priv->volume),
 		      "volume", vol,
 		      NULL);
 }
diff -ru last-exit-0.2/liblast-exit/player.h last-exit-0.2-mod/liblast-exit/player.h
--- last-exit-0.2/liblast-exit/player.h	2006-01-20 23:10:17.000000000 +0100
+++ last-exit-0.2-mod/liblast-exit/player.h	2006-03-01 03:01:22.000000000 +0100
@@ -46,6 +46,8 @@
 Player *player_new (void);
 gboolean player_set_location (Player *player,
 			      const char *location);
+void player_set_save_location (Player *player,
+			      const char *location);
 void player_play (Player *player);
 void player_stop (Player *player);
 
diff -ru last-exit-0.2/src/Driver.cs last-exit-0.2-mod/src/Driver.cs
--- last-exit-0.2/src/Driver.cs	2006-02-10 02:00:37.000000000 +0100
+++ last-exit-0.2-mod/src/Driver.cs	2006-03-01 04:46:26.000000000 +0100
@@ -105,7 +105,8 @@
 		}
 
 		public static void Exit () {
-			Environment.Exit (0);
+			player.Stop();
+			Application.Quit ();
 		}
 
 		[DllImport ("libc")]
diff -ru last-exit-0.2/src/Player.cs last-exit-0.2-mod/src/Player.cs
--- last-exit-0.2/src/Player.cs	2006-02-12 02:25:44.000000000 +0100
+++ last-exit-0.2-mod/src/Player.cs	2006-03-01 03:01:44.000000000 +0100
@@ -61,6 +61,15 @@
 				player_set_location (Raw, value);
 			}
 		}
+		
+		[DllImport ("liblastexit")]
+			private static extern void player_set_save_location (IntPtr player, 
+									string filename);
+		public string SaveLocation {
+			set {
+				player_set_save_location (Raw, value);
+			}
+		}
 
 		[DllImport ("liblastexit")]
 			private static extern void player_play (IntPtr player);
diff -ru last-exit-0.2/src/PlayerWindow.cs last-exit-0.2-mod/src/PlayerWindow.cs
--- last-exit-0.2/src/PlayerWindow.cs	2006-02-16 01:23:16.000000000 +0100
+++ last-exit-0.2-mod/src/PlayerWindow.cs	2006-03-01 04:56:00.000000000 +0100
@@ -49,6 +49,7 @@
 		private UrlLabel song_label;
 
 		[Glade.Widget] private Button info_button;
+		[Glade.Widget] private Button save_button;
 
 		[Glade.Widget] private ComboBox station_combo;
 		private StationStore stations;
@@ -132,7 +133,8 @@
 			tag_button.Clicked += new EventHandler (OnTagButtonClicked);
 			journal_button.Clicked += new EventHandler (OnJournalButtonClicked);
 			info_button.Clicked += new EventHandler (OnInfoButtonClicked);
-
+			save_button.Clicked += new EventHandler (OnSaveButtonClicked);
+			
 			// Volume
 			volume_button = new VolumeButton ();
 			volume_button_container.Add (volume_button);
@@ -421,7 +423,26 @@
 			i_window.Visible = true;
 			i_window.Response += new ResponseHandler (OnInfoWindowResponse);
 		}
-
+		
+		private void OnSaveButtonClicked (object o, EventArgs args)
+		{
+			FileChooserDialog filechooser = new FileChooserDialog("Choose Song directory", this, FileChooserAction.SelectFolder,
+								Stock.Cancel, ResponseType.Cancel,
+								Stock.Save, ResponseType.Accept);
+								
+			int response = filechooser.Run();
+			if ((ResponseType) response == ResponseType.Accept && current_song != null)
+			{
+				string artist = current_song.Artist.Replace("/","-");
+				string album = current_song.Album.Replace("/","-");
+				string track =  current_song.Track.Replace("/","-");
+				string filename = String.Format("{0}/{1} - {2} - {3}.mp3", filechooser.CurrentFolder, artist, album, track);
+				Console.WriteLine("Setting up to save song at: {0}", filename);
+				Driver.player.SaveLocation = filename;
+			}
+			filechooser.Destroy();
+		}
+		
 		private void OnVolumeChanged (int vol) 
 		{
 			Driver.player.Volume = vol;
@@ -449,6 +470,7 @@
 		private void OnNewSong () 
 		{
 			Driver.connection.GetMetadata ();
+			
 		}
 
 		private void OnCoverLoaded (Gdk.Pixbuf cover_pb) 

