diff --git a/src/Clients/Nereid/Nereid/PlayerInterface.cs b/src/Clients/Nereid/Nereid/PlayerInterface.cs
index ca1e1c2..6e658b1 100644
--- a/src/Clients/Nereid/Nereid/PlayerInterface.cs
+++ b/src/Clients/Nereid/Nereid/PlayerInterface.cs
@@ -74,6 +74,17 @@ namespace Nereid
         private CompositeTrackSourceContents composite_view;
         private ObjectListSourceContents object_view;
         private Label status_label;
+        private BansheeActionGroup actions;
+        private const string menu_xml = @"
+            <ui>
+                <popup name=""TrackInfoDisplayArtistMenu"">
+                    <menuitem action=""BrowseCurrentArtistAction""></menuitem>
+                </popup>
+                <popup name=""TrackInfoDisplayAlbumMenu"">
+                    <menuitem action=""BrowseCurrentAlbumAction""></menuitem>
+                </popup>
+            </ui>
+        ";
 
         public MainMenu MainMenu {
             get { return main_menu; }
@@ -122,6 +133,7 @@ namespace Nereid
 
             BuildPrimaryLayout ();
             ConnectEvents ();
+            RegisterActions ();
 
             ActionService.SourceActions.SourceView = this;
             composite_view.TrackView.HasFocus = true;
@@ -132,12 +144,36 @@ namespace Nereid
             base.OnShown ();
         }
 
+        private void RegisterActions ()
+        {
+            actions = new Banshee.Gui.BansheeActionGroup ("nereidplayerinterface");
+
+            actions.Add (new ActionEntry [] {
+            new ActionEntry ("BrowseCurrentArtistAction", Stock.Find,
+                Catalog.GetString ("Browse tracks by this artist"), null,
+                Catalog.GetString ("Browse tracks by this artist"),
+                OnBrowseCurrentArtist)
+            });
+
+            actions.Add (new ActionEntry [] {
+            new ActionEntry ("BrowseCurrentAlbumAction", Stock.Find,
+                Catalog.GetString ("Browse tracks from this album"), null,
+                Catalog.GetString ("Browse tracks from this album"),
+                OnBrowseCurrentAlbum)
+            });
+
+            actions.Actions.UIManager.AddUiFromString (menu_xml);
+            actions.Register ();
+        }
+
 #region System Overrides
 
         public override void Dispose ()
         {
             lock (this) {
                 Hide ();
+                if (actions != null)
+                    actions.Dispose ();
                 base.Dispose ();
                 Gtk.Application.Quit ();
             }
@@ -204,6 +240,8 @@ namespace Nereid
             ActionService.PopulateToolbarPlaceholder (header_toolbar, "/HeaderToolbar/SeekSlider", seek_slider);
 
             var track_info_display = new ClassicTrackInfoDisplay ();
+            track_info_display.ArtistSelected += OnTrackInfoArtistSelected;
+            track_info_display.AlbumSelected += OnTrackInfoAlbumSelected;
             track_info_display.Show ();
             var editable = TrackInfoDisplay.GetEditable (track_info_display);
             editable.Show ();
@@ -233,6 +271,52 @@ namespace Nereid
             }
         }
 
+        private void OnTrackInfoArtistSelected (object sender, TrackSelectedEventArgs e)
+        {
+            // TODO: Consider if source should change, if this feature should
+            //       only ever work in MusicLibrary, etc.
+            //ServiceManager.SourceManager.SetActiveSource (ServiceManager.SourceManager.MusicLibrary);
+            if (e.SelectedTrack == null || string.IsNullOrEmpty (e.SelectedTrack.ArtistName))
+                return;
+            string query =
+                Banshee.Query.BansheeQuery.ArtistField.ToTermString ("==", e.SelectedTrack.ArtistName);
+            // If the user clicks *again*, clear the search entry
+            if (view_container.SearchEntry.Query == query)
+                view_container.SearchEntry.Query = String.Empty;
+            else
+                view_container.SearchEntry.Query = query;
+        }
+
+        private void OnTrackInfoAlbumSelected (object sender, TrackSelectedEventArgs e)
+        {
+            // TODO: Consider if source should change, if this feature should
+            //       only ever work in MusicLibrary, etc.
+            //ServiceManager.SourceManager.SetActiveSource (ServiceManager.SourceManager.MusicLibrary);
+            if (e.SelectedTrack == null || string.IsNullOrEmpty (e.SelectedTrack.AlbumTitle))
+                return;
+            string query =
+                Banshee.Query.BansheeQuery.AlbumField.ToTermString ("==", e.SelectedTrack.AlbumTitle);
+            // If the user clicks *again*, clear the search entry
+            if (view_container.SearchEntry.Query == query)
+                view_container.SearchEntry.Query = String.Empty;
+            else
+                view_container.SearchEntry.Query = query;
+        }
+
+        private void OnBrowseCurrentArtist (object o, EventArgs args)
+        {
+            TrackInfo current_track = ServiceManager.PlayerEngine.CurrentTrack;
+            if (current_track != null)
+                OnTrackInfoArtistSelected (o, new TrackSelectedEventArgs (current_track));
+        }
+
+        private void OnBrowseCurrentAlbum (object o, EventArgs args)
+        {
+            TrackInfo current_track = ServiceManager.PlayerEngine.CurrentTrack;
+            if (current_track != null)
+                OnTrackInfoAlbumSelected (o, new TrackSelectedEventArgs (current_track));
+        }
+
         private void BuildViews ()
         {
             source_box = new VBox ();
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs
index 42eed54..9f06e3d 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ClassicTrackInfoDisplay.cs
@@ -27,9 +27,12 @@
 //
 
 using System;
+using System.Text;
+using System.Collections.Generic;
 using Gdk;
 using Gtk;
 using Cairo;
+using Mono.Unix;
 
 using Hyena.Gui;
 using Banshee.Collection;
@@ -37,6 +40,22 @@ using Banshee.Collection.Gui;
 
 namespace Banshee.Gui.Widgets
 {
+    public class TrackSelectedEventArgs : EventArgs
+    {
+        private TrackInfo selected_track;
+
+        public TrackSelectedEventArgs (TrackInfo selected_track) : base ()
+        {
+            this.selected_track = selected_track;
+        }
+
+        public TrackInfo SelectedTrack {
+            get {
+                return selected_track;
+            }
+        }
+    }
+
     public class ClassicTrackInfoDisplay : TrackInfoDisplay
     {
         private Gdk.Window event_window;
@@ -45,8 +64,16 @@ namespace Banshee.Gui.Widgets
         private uint popup_timeout_id;
         private bool in_popup;
         private bool in_thumbnail_region;
+        private bool in_artist_region;
+        private bool in_album_region;
+        private double artist_min_x, artist_max_x, album_min_x, album_max_x;
+        private static Gdk.Cursor hand_cursor = new Gdk.Cursor (Gdk.CursorType.Hand1);
+        private static Gdk.Cursor arrow_cursor = new Gdk.Cursor (Gdk.CursorType.Arrow);
+        private static Gdk.Color blue_color = new Gdk.Color (0, 0, 255);
+        private string link_color_hex;
+        private bool is_hovering;
         private Pango.Layout first_line_layout;
-        private Pango.Layout second_line_layout;
+        private List<Pango.Layout> second_line_layouts;
 
         public ClassicTrackInfoDisplay () : base ()
         {
@@ -75,6 +102,13 @@ namespace Banshee.Gui.Widgets
 
         public int ArtworkSpacing { get; set; }
 
+#region Events
+
+        public event EventHandler<TrackSelectedEventArgs> ArtistSelected;
+        public event EventHandler<TrackSelectedEventArgs> AlbumSelected;
+
+#endregion
+
 #region Widget Window Management
 
         protected override void OnRealized ()
@@ -92,6 +126,9 @@ namespace Banshee.Gui.Widgets
                 EventMask.PointerMotionMask |
                 EventMask.EnterNotifyMask |
                 EventMask.LeaveNotifyMask |
+                EventMask.ButtonReleaseMask |
+                EventMask.ButtonPressMask |
+                EventMask.Button1MotionMask |
                 EventMask.ExposureMask);
 
             WindowAttributesType attributes_mask =
@@ -112,6 +149,14 @@ namespace Banshee.Gui.Widgets
             base.OnUnrealized ();
         }
 
+        protected override void OnStyleSet (Style previous)
+        {
+            base.OnStyleSet (previous);
+
+            Gdk.Color link_color = Hyena.Gui.GtkUtilities.StyleGetProperty<Gdk.Color> (this, "link-color", blue_color);
+            link_color_hex = CairoExtensions.ColorGetHex (CairoExtensions.GdkColorToCairoColor (link_color), false);
+        }
+
         protected override void OnMapped ()
         {
             event_window.Show ();
@@ -156,10 +201,12 @@ namespace Banshee.Gui.Widgets
                 first_line_layout = null;
             }
 
-            if (second_line_layout != null) {
-                second_line_layout.FontDescription.Dispose ();
-                second_line_layout.Dispose ();
-                second_line_layout = null;
+            if (second_line_layouts != null && second_line_layouts.Count > 0) {
+                foreach (Pango.Layout layout in second_line_layouts) {
+                    layout.FontDescription.Dispose ();
+                    layout.Dispose ();
+                }
+                second_line_layouts.Clear ();
             }
         }
 
@@ -176,7 +223,7 @@ namespace Banshee.Gui.Widgets
             double offset = ArtworkSizeRequest + ArtworkSpacing, 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;
             int pango_width = (int)(width * Pango.Scale.PangoScale);
 
             if (first_line_layout == null) {
@@ -184,20 +231,62 @@ namespace Banshee.Gui.Widgets
                 first_line_layout.Ellipsize = Pango.EllipsizeMode.End;
             }
 
-            if (second_line_layout == null) {
-                second_line_layout = CairoExtensions.CreateLayout (this, cr);
-                second_line_layout.Ellipsize = Pango.EllipsizeMode.End;
-            }
+            // Reset artist/album region detection
+            album_min_x = album_max_x = artist_min_x = artist_max_x = 0;
 
             // Set up the text layouts
             first_line_layout.Width = pango_width;
-            second_line_layout.Width = pango_width;
 
             // 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> second_line_phrases = GetSecondLineText (track);
+
+            if (second_line_layouts == null)
+                second_line_layouts = new List<Pango.Layout> ();
+
+            for (int i = 0; i < second_line_phrases.Count; i++) {
+                Pango.Layout layout = null;
+                if (i >= second_line_layouts.Count) {
+                    layout = CairoExtensions.CreateLayout (this, cr);
+                    second_line_layouts.Add (layout);
+                } else
+                    layout = second_line_layouts [i];
+
+                string phrase_format = "{0}<span color=\"{1}\"{2}>{3}</span>{4}";
+
+                TrackInfoPhrase phrase = second_line_phrases [i];
+
+                if (phrase.Property == TrackInfoProperty.None) {
+                    layout.SetMarkup (string.Format (phrase_format,
+                                                     (i == 0 ? String.Empty : " "),
+                                                     CairoExtensions.ColorGetHex (TextLightColor, false),
+                                                     " size=\"small\"",
+                                                     GLib.Markup.EscapeText (phrase.Text),
+                                                     " "));
+                } else if (phrase.Property == TrackInfoProperty.AlbumName && AlbumSelected != null ||
+                           phrase.Property == TrackInfoProperty.ArtistName && ArtistSelected != null) {
+                    layout.SetMarkup (string.Format (phrase_format,
+                                                     String.Empty,
+                                                     link_color_hex,
+                                                     String.Empty,
+                                                     GLib.Markup.EscapeText (phrase.Text),
+                                                     String.Empty));
+                } else {
+                    layout.SetMarkup (string.Format (phrase_format,
+                                                     String.Empty,
+                                                     CairoExtensions.ColorGetHex (TextColor, false),
+                                                     String.Empty,
+                                                     GLib.Markup.EscapeText (phrase.Text),
+                                                     String.Empty));
+                }
+
+                int phrase_width, phrase_height;
+                layout.GetPixelSize (out phrase_width, out phrase_height);
+                if (phrase_height > sl_height)
+                    sl_height = phrase_height;
+            }
 
             if (fl_height + sl_height > Allocation.Height) {
                 SetSizeRequest (-1, fl_height + sl_height);
@@ -219,7 +308,25 @@ namespace Banshee.Gui.Widgets
             }
 
             cr.MoveTo (x, y + fl_height);
-            PangoCairoHelper.ShowLayout (cr, second_line_layout);
+            for (int i = 0; i < second_line_phrases.Count; i++) {
+                Pango.Layout layout = second_line_layouts [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 (second_line_phrases [i].Property == TrackInfoProperty.AlbumName) {
+                    album_min_x = x - Allocation.X;
+                    album_max_x = next_x - Allocation.X;
+                } else if (second_line_phrases [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);
+            }
         }
 
 #endregion
@@ -241,9 +348,63 @@ namespace Banshee.Gui.Widgets
         protected override bool OnMotionNotifyEvent (EventMotion evnt)
         {
             in_thumbnail_region = evnt.X <= Allocation.Height;
+            in_artist_region =
+                evnt.X >= artist_min_x &&
+                evnt.X <= artist_max_x &&
+                evnt.Y >= Allocation.Y / 2;
+            in_album_region =
+                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 != null) {
+                ArtistSelected (this, new TrackSelectedEventArgs (CurrentTrack));
+            } else if (in_album_region && CurrentTrack != null && AlbumSelected != null) {
+                AlbumSelected (this, new TrackSelectedEventArgs (CurrentTrack));
+            }
+
+            return false;
+        }
+
+        protected override bool OnButtonPressEvent (EventButton evnt)
+        {
+            // Only handle right-click
+            if (evnt.Button != 3)
+                return false;
+
+            ShowPopupMenu ();
+
+            return true;
+        }
+
+        protected virtual void ShowPopupMenu ()
+        {
+            if (CurrentTrack == null ||
+                (!in_artist_region && !in_album_region))
+                return;
+
+            InterfaceActionService action_service =
+                Banshee.ServiceStack.ServiceManager.Get<Banshee.Gui.InterfaceActionService> ();
+            Menu menu;
+
+            if (in_artist_region)
+                menu = action_service.UIManager.GetWidget ("/TrackInfoDisplayArtistMenu") as Menu;
+            else // in album region
+                menu = action_service.UIManager.GetWidget ("/TrackInfoDisplayAlbumMenu") as Menu;
+
+            menu.Popup (null, null, null, 3, Gtk.Global.CurrentEventTime);
+            menu.ShowAll ();
+        }
+
         private void OnPopupEnterNotifyEvent (object o, EnterNotifyEventArgs args)
         {
             in_popup = true;
@@ -288,6 +449,18 @@ namespace Banshee.Gui.Widgets
             return true;
         }
 
+        private void SetMouse (Gdk.Window window)
+        {
+            if (!is_hovering &&
+                    (in_artist_region && ArtistSelected != null || in_album_region && AlbumSelected != null)) {
+                window.Cursor = hand_cursor;
+                is_hovering = true;
+            } else if (is_hovering && !in_artist_region && !in_album_region) {
+                window.Cursor = arrow_cursor;
+                is_hovering = false;
+            }
+        }
+
 #endregion
 
 #region Popup Window
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs
index 61ee69c..4b44e7d 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/LargeTrackInfoDisplay.cs
@@ -190,21 +190,27 @@ namespace Banshee.Gui.Widgets
             int pango_width = (int)(width * Pango.Scale.PangoScale);
 
             string first_line = GetFirstLineText (track);
+            string second_line = String.Empty;
+            string third_line = String.Empty;
 
-            // 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 = String.Empty;
-            int split_pos = line.LastIndexOf ("<span");
-            if (split_pos >= 0
-                // Check that there are at least 3 spans in the string, else this
-                // will break for tracks with missing artist or album info.
-                && StringUtil.SubstringCount (line, "<span") >= 3) {
-
-                second_line = line.Substring (0, Math.Max (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));
+            IList<TrackInfoPhrase> second_line_phrases = GetSecondLineText (track);
+
+            string line_format =
+                "<span color=\"{0}\" size=\"small\">{1} </span><span color=\"{2}\" size=\"small\">{3}</span>";
+
+            if (second_line_phrases.Count >= 2) {
+                second_line = string.Format (line_format,
+                                             CairoExtensions.ColorGetHex (TextLightColor, false),
+                                             GLib.Markup.EscapeText (second_line_phrases [0].Text),
+                                             CairoExtensions.ColorGetHex (TextColor, false),
+                                             GLib.Markup.EscapeText (second_line_phrases [1].Text));
+            }
+            if (second_line_phrases.Count >= 4) {
+                third_line = string.Format (line_format,
+                                             CairoExtensions.ColorGetHex (TextLightColor, false),
+                                             GLib.Markup.EscapeText (second_line_phrases [2].Text),
+                                             CairoExtensions.ColorGetHex (TextColor, false),
+                                             GLib.Markup.EscapeText (second_line_phrases [3].Text));
             }
 
             if (first_line_layout == null) {
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs
index bfe4445..98d9c6b 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TrackInfoDisplay.cs
@@ -491,81 +491,83 @@ namespace Banshee.Gui.Widgets
             return String.Format ("<b>{0}</b>", GLib.Markup.EscapeText (track.DisplayTrackTitle));
         }
 
-        protected virtual string GetSecondLineText (TrackInfo track)
+        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 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 (
-                    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)) {
+                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 (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);
-            }
-
-            return String.Format ("<span color=\"{0}\">{1}</span>",
-                CairoExtensions.ColorGetHex (TextColor, false),
-                markup);
-        }
-
-        private string MarkupFormat (string fmt, params string [] args)
-        {
-            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>";
-
-            for (int i = 0; i < args.Length; i++) {
-                new_args[i + 2] = GLib.Markup.EscapeText (args[i]);
+                phrases.AddRange (GetByFrom (track.ArtistName, track.DisplayArtistName, track.AlbumTitle,
+                    track.DisplayAlbumTitle, true));
             }
 
-            return String.Format (fmt, new_args);
+            return phrases;
         }
 
-        private string GetByFrom (string artist, string display_artist, string album, string display_album, bool unknown_ok)
+        private IList<TrackInfoPhrase> GetByFrom (string artist, string display_artist, string album,
+            string display_album, bool unknown_ok)
         {
+            List<TrackInfoPhrase> phrases = new List<TrackInfoPhrase> ();
 
             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;
         }
     }
 }
diff --git a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs
index 6ebe4d8..ffc9749 100644
--- a/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs
+++ b/src/Extensions/Banshee.PlayQueue/Banshee.PlayQueue/PlayQueueActions.cs
@@ -32,8 +32,12 @@ using Mono.Unix;
 using Gtk;
 
 using Hyena;
-
+using Hyena.Query;
+using Banshee.Query;
+using Banshee.Collection;
+using Banshee.Collection.Database;
 using Banshee.ServiceStack;
+using Banshee.SmartPlaylist;
 using Banshee.Sources;
 
 namespace Banshee.PlayQueue
@@ -52,6 +56,20 @@ namespace Banshee.PlayQueue
                     OnAddToPlayQueue)
             });
 
+            Add (new ActionEntry [] {
+                new ActionEntry ("AddArtistToPlayQueueAction", Stock.Add,
+                    Catalog.GetString ("Add artist to Play Queue"), null,
+                    Catalog.GetString ("Append artist's songs to the play queue"),
+                    OnAddArtistToPlayQueue)
+            });
+
+            Add (new ActionEntry [] {
+                new ActionEntry ("AddAlbumToPlayQueueAction", Stock.Add,
+                    Catalog.GetString ("Add album to Play Queue"), null,
+                    Catalog.GetString ("Append album's songs to the play queue"),
+                    OnAddAlbumToPlayQueue)
+            });
+
             AddImportant (
                 new ActionEntry ("RefreshPlayQueueAction", Stock.Refresh,
                     Catalog.GetString ("Refresh"), null,
@@ -84,6 +102,8 @@ namespace Banshee.PlayQueue
 
             playqueue.Updated += OnUpdated;
             ServiceManager.SourceManager.ActiveSourceChanged += OnSourceUpdated;
+            ServiceManager.PlaybackController.SourceChanged += OnUpdated;
+            ServiceManager.PlaybackController.TrackStarted += OnUpdated;
 
             OnUpdated (null, null);
 
@@ -94,16 +114,45 @@ namespace Banshee.PlayQueue
         {
             playqueue.Updated -= OnUpdated;
             ServiceManager.SourceManager.ActiveSourceChanged -= OnSourceUpdated;
+            ServiceManager.PlaybackController.SourceChanged -= OnUpdated;
+            ServiceManager.PlaybackController.TrackStarted -= OnUpdated;
             base.Dispose ();
         }
 
         #region Action Handlers
-
         private void OnAddToPlayQueue (object o, EventArgs args)
         {
             playqueue.AddSelectedTracks (ServiceManager.SourceManager.ActiveSource);
         }
 
+        private void OnAddArtistToPlayQueue (object o, EventArgs args)
+        {
+            DatabaseTrackInfo current_track = ServiceManager.PlayerEngine.CurrentTrack as DatabaseTrackInfo;
+            if (current_track == null)
+                return;
+            string query_string = BansheeQuery.ArtistField.ToTermString ("==", current_track.ArtistName);
+
+            QueryNode query = UserQueryParser.Parse (query_string, BansheeQuery.FieldSet);
+            SmartPlaylistSource smart_source = CreateSmartPlaylist (query, current_track.PrimarySource);
+
+            playqueue.AddAllTracks (smart_source);
+            smart_source.Unmap ();
+        }
+
+        private void OnAddAlbumToPlayQueue (object o, EventArgs args)
+        {
+            DatabaseTrackInfo current_track = ServiceManager.PlayerEngine.CurrentTrack as DatabaseTrackInfo;
+            if (current_track == null)
+                return;
+            string query_string = BansheeQuery.AlbumField.ToTermString ("==", current_track.AlbumTitle);
+
+            QueryNode query = UserQueryParser.Parse (query_string, BansheeQuery.FieldSet);
+            SmartPlaylistSource smart_source = CreateSmartPlaylist (query, current_track.PrimarySource);
+
+            playqueue.AddAllTracks (smart_source);
+            smart_source.Unmap ();
+        }
+
         private void OnClearPlayQueue (object o, EventArgs args)
         {
             playqueue.Clear ();
@@ -127,6 +176,22 @@ namespace Banshee.PlayQueue
 
         #endregion
 
+        private SmartPlaylistSource CreateSmartPlaylist (QueryNode query, PrimarySource primarySource)
+        {
+            QueryOrder order = null;
+            QueryLimit limit = null;
+            IntegerQueryValue limit_value = null;
+
+            // Construct a temporary, internal smart playlist for the query
+            SmartPlaylistSource smart_source =
+                new SmartPlaylistSource ("templist", query, order, limit, limit_value, primarySource);
+            smart_source.IsTemporary = true;
+            smart_source.Save ();
+            smart_source.Reload ();
+
+            return smart_source;
+        }
+
         private void OnSourceUpdated (SourceEventArgs args)
         {
             OnUpdated (null, null);
@@ -148,6 +213,19 @@ namespace Banshee.PlayQueue
                 UpdateAction ("ClearPlayQueueOnQuitAction", !playqueue.Populate);
                 UpdateAction ("AddToPlayQueueAction", db_source != null && db_source != playqueue, true);
             }
+
+            DatabaseTrackInfo current_track = ServiceManager.PlayerEngine.CurrentTrack as DatabaseTrackInfo;
+            ISource playingSource = (current_track != null ? current_track.PrimarySource : null) ??
+                ServiceManager.PlaybackController.Source;
+
+            if (playingSource != null) {
+                DatabaseSource db_source = playingSource as DatabaseSource ?? playingSource.Parent as DatabaseSource;
+                PrimarySource primary_source = playingSource as PrimarySource ?? playingSource.Parent as PrimarySource;
+                bool visible = db_source != null && db_source != playqueue &&
+                    primary_source != null && primary_source.SupportsPlaylists;
+                UpdateAction ("AddArtistToPlayQueueAction", visible, true);
+                UpdateAction ("AddAlbumToPlayQueueAction", visible, true);
+            }
         }
     }
 }
diff --git a/src/Extensions/Banshee.PlayQueue/Resources/GlobalUI.xml b/src/Extensions/Banshee.PlayQueue/Resources/GlobalUI.xml
index 676fdd5..c2f1d64 100644
--- a/src/Extensions/Banshee.PlayQueue/Resources/GlobalUI.xml
+++ b/src/Extensions/Banshee.PlayQueue/Resources/GlobalUI.xml
@@ -11,4 +11,10 @@
             <menuitem name="AddToPlayQueue" action="AddToPlayQueueAction"></menuitem>
         </placeholder>
     </popup>
+    <popup name="TrackInfoDisplayArtistMenu">
+        <menuitem action="AddArtistToPlayQueueAction"></menuitem>
+    </popup>
+    <popup name="TrackInfoDisplayAlbumMenu">
+        <menuitem action="AddAlbumToPlayQueueAction"></menuitem>
+    </popup>
 </ui>
\ No newline at end of file
diff --git a/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs b/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs
index 7b31440..2e45b22 100644
--- a/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs
+++ b/src/Libraries/Hyena.Gui/Hyena.Gui/GtkUtilities.cs
@@ -142,7 +142,10 @@ namespace Hyena.Gui
 
         public static T StyleGetProperty<T> (Widget widget, string property, T default_value)
         {
-            object result = widget.StyleGetProperty (property);
+            object result = null;
+            try {
+                result = widget.StyleGetProperty (property);
+            } catch {}
             return result != null && result.GetType () == typeof (T) ? (T)result : default_value;
         }
 
