Index: src/Clients/Nereid/Nereid/PlayerInterface.cs
===================================================================
--- src/Clients/Nereid/Nereid/PlayerInterface.cs	(revision 4374)
+++ src/Clients/Nereid/Nereid/PlayerInterface.cs	(working copy)
@@ -154,7 +154,9 @@
             seek_slider.Show ();
             ActionService.PopulateToolbarPlaceholder (header_toolbar, "/HeaderToolbar/SeekSlider", seek_slider);
             
-            TrackInfoDisplay track_info_display = new ClassicTrackInfoDisplay ();
+            ClassicTrackInfoDisplay track_info_display = new ClassicTrackInfoDisplay ();
+			track_info_display.ArtistSelected += OnTrackInfoArtistSelected;
+			track_info_display.AlbumSelected += OnTrackInfoAlbumSelected;
             track_info_display.Show ();
             ActionService.PopulateToolbarPlaceholder (header_toolbar, "/HeaderToolbar/TrackInfoDisplay", track_info_display, true);
             
@@ -162,6 +164,26 @@
             volume_button.Show ();
             ActionService.PopulateToolbarPlaceholder (header_toolbar, "/HeaderToolbar/VolumeButton", volume_button);
         }
+		
+		private void OnTrackInfoArtistSelected (TrackInfo selected_track)
+		{
+			// TODO: Consider if source should change, if this feature should
+			//       only ever work in MusicLibrary, etc.
+			//ServiceManager.SourceManager.SetActiveSource (ServiceManager.SourceManager.MusicLibrary);
+			if (selected_track == null)
+				return;
+			view_container.SearchEntry.Query = "artist==\"" + selected_track.ArtistName + "\"";
+		}
+		
+		private void OnTrackInfoAlbumSelected (TrackInfo selected_track)
+		{
+			// TODO: Consider if source should change, if this feature should
+			//       only ever work in MusicLibrary, etc.
+			//ServiceManager.SourceManager.SetActiveSource (ServiceManager.SourceManager.MusicLibrary);
+			if (selected_track == null)
+				return;
+			view_container.SearchEntry.Query = "album==\"" + selected_track.AlbumTitle + "\"";
+		}
 
         private void BuildViews ()
         {
Index: src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs
===================================================================
--- src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs	(revision 4401)
+++ src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs	(working copy)
@@ -166,15 +166,32 @@
             
             // FIXME: This is incredibly bad, but we don't want to break
             // translations right now. It needs to be replaced for 1.4!!
-            string line = GetSecondLineText (track);
-            string second_line = line, third_line = line;
-            int split_pos = line.LastIndexOf ("<span");
-            if (split_pos >= 0) {
-                second_line = line.Substring (0, split_pos - 1) + "</span>";
-                third_line = String.Format ("<span color=\"{0}\">{1}",
-                    CairoExtensions.ColorGetHex (TextColor, false),
-                    line.Substring (split_pos, line.Length - split_pos));
-            }
+            //string line = GetSecondLineText (track);
+			IList<TrackInfoPhrase> secondLinePhrases = GetSecondLineText (track);
+			string second_line =
+				"<span color=\"" +
+					CairoExtensions.ColorGetHex (TextLightColor, false) +
+					"\" size =\"small\">" +
+					GLib.Markup.EscapeText (secondLinePhrases [0].Text) +
+					" " +
+					"</span>" +
+				"<span color=\"" +
+					CairoExtensions.ColorGetHex (TextColor, false) +
+					"\" size =\"small\">" +
+					GLib.Markup.EscapeText (secondLinePhrases [1].Text) +
+					"</span>";
+			string third_line =
+				"<span color=\"" +
+					CairoExtensions.ColorGetHex (TextLightColor, false) +
+					"\" size =\"small\">" +
+					GLib.Markup.EscapeText (secondLinePhrases [2].Text) +
+					" " +
+					"</span>" +
+				"<span color=\"" +
+					CairoExtensions.ColorGetHex (TextColor, false) +
+					"\" size =\"small\">" +
+					GLib.Markup.EscapeText (secondLinePhrases [3].Text) +
+					"</span>";
 
             // Set up the text layouts
             Pango.Layout first_line_layout = null;
Index: src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs
===================================================================
--- src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs	(revision 4401)
+++ src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs	(working copy)
@@ -418,82 +418,77 @@
         {
             return String.Format ("<b>{0}</b>", GLib.Markup.EscapeText (track.DisplayTrackTitle));
         }
+		
+		protected enum TrackInfoProperty {
+			None,
+			ArtistName,
+			AlbumName,
+			ReleaseDate,
+			Unknown
+		}
+		protected struct TrackInfoPhrase {
+			public string Text;
+			public TrackInfoProperty Property;
+			public TrackInfoPhrase (string text, TrackInfoProperty property)
+			{
+				Text = text;
+				Property = property;
+			}
+		}
         
-        protected virtual string GetSecondLineText (TrackInfo track)
+        protected virtual IList<TrackInfoPhrase> GetSecondLineText (TrackInfo track)
         {
-            string markup = null;
+			List<TrackInfoPhrase> phrases = new List<TrackInfoPhrase> ();
             Banshee.Streaming.RadioTrackInfo radio_track = track as Banshee.Streaming.RadioTrackInfo;
 
             if ((track.MediaAttributes & TrackMediaAttributes.Podcast) != 0) {
-                // Translators: {0} and {1} are for markup so ignore them, {2} and {3}
-                // are Podcast Name and Published Date, respectively;
-                // e.g. 'from BBtv published 7/26/2007'
-                markup = MarkupFormat (Catalog.GetString ("{0}from{1} {2} {0}published{1} {3}"), 
-                    track.DisplayAlbumTitle, track.ReleaseDate.ToShortDateString ());
+				phrases.Add (new TrackInfoPhrase (Catalog.GetString ("from"), TrackInfoProperty.None));
+				phrases.Add (new TrackInfoPhrase (track.DisplayAlbumTitle, TrackInfoProperty.AlbumName));
+				phrases.Add (new TrackInfoPhrase (Catalog.GetString ("published"), TrackInfoProperty.None));
+				phrases.Add (new TrackInfoPhrase (track.ReleaseDate.ToShortDateString (), TrackInfoProperty.ReleaseDate));
             } else if (radio_track != null && radio_track.ParentTrack != null) {
                 // This is complicated because some radio streams send tags when the song changes, and we
                 // want to display them if they do.  But if they don't, we want it to look good too, so we just
                 // display the station name for the second line.
-                string by_from = GetByFrom (
+				phrases.AddRange (GetByFrom (
                     track.ArtistName == radio_track.ParentTrack.ArtistName ? null : track.ArtistName, track.DisplayArtistName,
                     track.AlbumTitle == radio_track.ParentTrack.AlbumTitle ? null : track.AlbumTitle, track.DisplayAlbumTitle, false
-                );
+                ));
                 
-                if (String.IsNullOrEmpty (by_from)) {
+				if (phrases.Count == 0) {
                     // simply: "Chicago Public Radio" or whatever the artist name is
-                    markup = GLib.Markup.EscapeText (radio_track.ParentTrack.ArtistName ?? Catalog.GetString ("Unknown Stream"));
+					phrases.Add (new TrackInfoPhrase (radio_track.ParentTrack.ArtistName ?? Catalog.GetString ("Unknown Stream"), TrackInfoProperty.Unknown));
                 } else {
-                    // Translators: {0} and {1} are markup so ignore them, {2} is the name of the radio station
-                    string on = MarkupFormat (Catalog.GetString ("{0}on{1} {2}"), radio_track.ParentTrack.TrackTitle);
-                    
-                    // Translators: {0} is the "from {album} by {artist}" type string, and {1} is the "on {radio station name}" string
-                    markup = String.Format (Catalog.GetString ("{0} {1}"), by_from, on);
+				phrases.Add (new TrackInfoPhrase (Catalog.GetString ("on"), TrackInfoProperty.None));
+				phrases.Add (new TrackInfoPhrase (radio_track.ParentTrack.TrackTitle, TrackInfoProperty.Unknown));
                 }
             } else {
-                markup = GetByFrom (track.ArtistName, track.DisplayArtistName, track.AlbumTitle, track.DisplayAlbumTitle, true);
+                phrases.AddRange (GetByFrom (track.ArtistName, track.DisplayArtistName, track.AlbumTitle, track.DisplayAlbumTitle, true));
             }
             
-            return String.Format ("<span color=\"{0}\">{1}</span>",  
-                CairoExtensions.ColorGetHex (TextColor, false),
-                markup);
+			return phrases;
         }
         
-        private string MarkupFormat (string fmt, params string [] args)
+        private IList<TrackInfoPhrase> GetByFrom (string artist, string display_artist, string album, string display_album, bool unknown_ok)
         {
-            string [] new_args = new string [args.Length + 2];
-            new_args[0] = String.Format ("<span color=\"{0}\" size=\"small\">", 
-                CairoExtensions.ColorGetHex (TextLightColor, false));
-            new_args[1] = "</span>";
+			List<TrackInfoPhrase> phrases = new List<TrackInfoPhrase> ();
             
-            for (int i = 0; i < args.Length; i++) {
-                new_args[i + 2] = GLib.Markup.EscapeText (args[i]);
-            }
-            
-            return String.Format (fmt, new_args);
-        }
-        
-        private string GetByFrom (string artist, string display_artist, string album, string display_album, bool unknown_ok)
-        {
-            
             bool has_artist = !String.IsNullOrEmpty (artist);
             bool has_album = !String.IsNullOrEmpty (album);
 
-            string markup = null;
             if (has_artist && has_album) {
-                // Translators: {0} and {1} are for markup so ignore them, {2} and {3}
-                // are Artist Name and Album Title, respectively;
-                // e.g. 'by Parkway Drive from Killing with a Smile'
-                markup = MarkupFormat (Catalog.GetString ("{0}by{1} {2} {0}from{1} {3}"), display_artist, display_album);
+				phrases.Add (new TrackInfoPhrase (Catalog.GetString ("by"), TrackInfoProperty.None));
+				phrases.Add (new TrackInfoPhrase (display_artist, TrackInfoProperty.ArtistName));
+				phrases.Add (new TrackInfoPhrase (Catalog.GetString ("from"), TrackInfoProperty.None));
+				phrases.Add (new TrackInfoPhrase (display_album, TrackInfoProperty.AlbumName));
             } else if (has_album) {
-                // Translators: {0} and {1} are for markup so ignore them, {2} is for Album Title;
-                // e.g. 'from Killing with a Smile'
-                markup = MarkupFormat (Catalog.GetString ("{0}from{1} {2}"), display_album);
+				phrases.Add (new TrackInfoPhrase (Catalog.GetString ("from"), TrackInfoProperty.None));
+				phrases.Add (new TrackInfoPhrase (display_album, TrackInfoProperty.AlbumName));
             } else if (has_artist || unknown_ok) {
-                // Translators: {0} and {1} are for markup so ignore them, {2} is for Artist Name;
-                // e.g. 'by Parkway Drive'
-                markup = MarkupFormat (Catalog.GetString ("{0}by{1} {2}"), display_artist);
+				phrases.Add (new TrackInfoPhrase (Catalog.GetString ("by"), TrackInfoProperty.None));
+				phrases.Add (new TrackInfoPhrase (display_artist, TrackInfoProperty.ArtistName));
             }
-            return markup;
+			return phrases;
         }
         
         protected void SurfaceExpire (Gdk.Pixbuf pixbuf)
Index: src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs
===================================================================
--- src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs	(revision 4401)
+++ src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs	(working copy)
@@ -27,6 +27,8 @@
 //
 
 using System;
+using System.Text;
+using System.Collections.Generic;
 using Gdk;
 using Gtk;
 using Cairo;
@@ -45,6 +47,9 @@
         private uint popup_timeout_id;
         private bool in_popup;
         private bool in_thumbnail_region;
+		private bool in_artist_region;
+		private bool in_album_region;
+		double artist_min_x, artist_max_x, album_min_x, album_max_x;
         
         public ClassicTrackInfoDisplay () : base ()
         {
@@ -59,6 +64,14 @@
             base.Dispose ();
             HidePopup ();
         }
+		
+#region Events
+		
+		public delegate void TrackSelectedHandler (TrackInfo current_track);
+		public event TrackSelectedHandler ArtistSelected;
+		public event TrackSelectedHandler AlbumSelected;
+		
+#endregion
         
 #region Widget Window Management
         
@@ -77,6 +90,9 @@
                 EventMask.PointerMotionMask |
                 EventMask.EnterNotifyMask |
                 EventMask.LeaveNotifyMask |
+			                             EventMask.ButtonReleaseMask |
+			                             EventMask.ButtonPressMask |
+			                             EventMask.Button1MotionMask |
                 EventMask.ExposureMask);
             
             WindowAttributesType attributes_mask =
@@ -146,21 +162,61 @@
             double offset = Allocation.Height + 10, y = 0;
             double x = Allocation.X + offset;
             double width = Allocation.Width - offset;
-            int fl_width, fl_height, sl_width, sl_height;
+            int fl_width, fl_height, sl_height = 0;
 
             // Set up the text layouts
             Pango.Layout first_line_layout = null;
             CairoExtensions.CreateLayout (this, cr, ref first_line_layout);
             first_line_layout.Width = (int)(width * Pango.Scale.PangoScale);
             first_line_layout.Ellipsize = Pango.EllipsizeMode.End;
-                        
-            Pango.Layout second_line_layout = first_line_layout.Copy ();
             
             // Compute the layout coordinates
             first_line_layout.SetMarkup (GetFirstLineText (track));
             first_line_layout.GetPixelSize (out fl_width, out fl_height);
-            second_line_layout.SetMarkup (GetSecondLineText (track));
-            second_line_layout.GetPixelSize (out sl_width, out sl_height);
+			
+			IList<TrackInfoPhrase> secondLinePhrases = GetSecondLineText (track);
+			
+			List<Pango.Layout> secondLineLayouts = new List<Pango.Layout> ();
+			
+			for (int i = 0; i < secondLinePhrases.Count; i++) {
+				Pango.Layout layout = null;
+				CairoExtensions.CreateLayout (this, cr, ref layout);
+				StringBuilder builder = new StringBuilder ();
+				
+				TrackInfoPhrase phrase = secondLinePhrases [i];
+				
+				if (phrase.Property == TrackInfoProperty.None) {
+					builder.Append ("<span color=\"");
+					builder.Append (CairoExtensions.ColorGetHex (TextLightColor, false));
+					builder.Append ("\" size =\"small\">");
+					builder.Append (GLib.Markup.EscapeText (
+					                                        (i == 0 ? string.Empty : " ") +
+					                                        phrase.Text));
+					builder.Append ("</span> ");
+				} else if (phrase.Property == TrackInfoProperty.AlbumName ||
+				           phrase.Property == TrackInfoProperty.ArtistName) {
+					builder.Append ("<span color=\"");
+					builder.Append ("#0000ff");
+					builder.Append ("\">");
+					builder.Append (GLib.Markup.EscapeText (phrase.Text));
+					builder.Append ("</span>");
+				} else {
+					builder.Append ("<span color=\"");
+					builder.Append (CairoExtensions.ColorGetHex (TextColor, false));
+					builder.Append ("\">");
+					builder.Append (GLib.Markup.EscapeText (phrase.Text));
+					builder.Append ("</span>");
+				}
+				
+				layout.SetMarkup (builder.ToString ());
+				
+				int phrase_width, phrase_height;
+				layout.GetPixelSize (out phrase_width, out phrase_height);
+				if (phrase_height > sl_height)
+					sl_height = phrase_height;
+				
+				secondLineLayouts.Add (layout);
+			}
             
             if (fl_height + sl_height > Allocation.Height) {
                 SetSizeRequest (-1, fl_height + sl_height);
@@ -179,15 +235,35 @@
 
             if (!renderArtistAlbum) {
                 first_line_layout.Dispose ();
-                second_line_layout.Dispose ();
+				foreach (Pango.Layout layout in secondLineLayouts)
+					layout.Dispose ();
                 return;
             }
             
             cr.MoveTo (x, y + fl_height);
-            PangoCairoHelper.ShowLayout (cr, second_line_layout);
+			for (int i = 0; i < secondLineLayouts.Count; i++) {
+				Pango.Layout layout = secondLineLayouts [i];
+				int phrase_width, phrase_height;
+				layout.GetPixelSize (out phrase_width, out phrase_height);
+				
+				PangoCairoHelper.ShowLayout (cr, layout);
+				double next_x = x + phrase_width;
+				
+				if (secondLinePhrases [i].Property == TrackInfoProperty.AlbumName) {
+					album_min_x = x - Allocation.X;
+					album_max_x = next_x - Allocation.X;
+				} else if (secondLinePhrases [i].Property == TrackInfoProperty.ArtistName) {
+					artist_min_x = x - Allocation.X;
+					artist_max_x = next_x - Allocation.X;
+				}
+				
+				x = next_x;
+				cr.MoveTo (x, y + fl_height);
+			}
             
             first_line_layout.Dispose ();
-            second_line_layout.Dispose ();
+			foreach (Pango.Layout layout in secondLineLayouts)
+				layout.Dispose ();
         }
         
 #endregion
@@ -209,8 +285,43 @@
         protected override bool OnMotionNotifyEvent (EventMotion evnt)
         {
             in_thumbnail_region = evnt.X <= Allocation.Height;
+			in_artist_region = //evnt.X >= Allocation.Height + 10 &&
+				evnt.X >= artist_min_x &&
+					evnt.X <= artist_max_x &&
+				evnt.Y >= Allocation.Y / 2;
+			in_album_region = //evnt.X >= Allocation.Height + 10 &&
+				evnt.X >= album_min_x &&
+					evnt.X <= album_max_x &&
+				evnt.Y >= Allocation.Y / 2;
+			SetMouse (evnt.Window);
             return ShowHideCoverArt ();
         }
+		
+		protected override bool OnButtonReleaseEvent (EventButton evnt)
+		{
+			// Only handle left-click
+			if (evnt.Button != 1)
+				return false;
+			
+			if (in_artist_region && CurrentTrack != null) {
+				ArtistSelected (CurrentTrack);
+			} else if (in_album_region && CurrentTrack != null) {
+				AlbumSelected (CurrentTrack);
+			}
+			
+			return false;
+		}
+		
+//		protected override bool OnButtonPressEvent (EventButton evnt)
+//		{
+//			// Only handle right-click
+//			if (evnt.Button != 3)
+//				return false;
+//			
+//			Hyena.Log.Debug ("A right-click!");
+//			
+//			return false;
+//		}
         
         private void OnPopupEnterNotifyEvent (object o, EnterNotifyEventArgs args)
         {
@@ -255,6 +366,14 @@
             
             return true;
         }
+		
+		private void SetMouse (Gdk.Window window)
+		{
+			if (in_artist_region || in_album_region)
+				window.Cursor = new Cursor (CursorType.Hand1);
+			else
+				window.Cursor = new Cursor (CursorType.Arrow);
+		}
 
 #endregion
 
