banshee r4168 - in trunk/banshee: . src/Clients/Nereid/Nereid src/Core/Banshee.ThickClient/Banshee.Gui src/Core/Banshee.Widgets/Banshee.Widgets src/Extensions/Banshee.Lastfm src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations src/Extensions/Banshee.Lastfm/Resources src/Extensions/Banshee.Lastfm/ThemeIcons/48x48 src/Libraries/Lastfm src/Libraries/Lastfm/Lastfm.Data
- From: gburt svn gnome org
- To: svn-commits-list gnome org
- Subject: banshee r4168 - in trunk/banshee: . src/Clients/Nereid/Nereid src/Core/Banshee.ThickClient/Banshee.Gui src/Core/Banshee.Widgets/Banshee.Widgets src/Extensions/Banshee.Lastfm src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations src/Extensions/Banshee.Lastfm/Resources src/Extensions/Banshee.Lastfm/ThemeIcons/48x48 src/Libraries/Lastfm src/Libraries/Lastfm/Lastfm.Data
- Date: Thu, 19 Jun 2008 01:20:55 +0000 (UTC)
Author: gburt
Date: Thu Jun 19 01:20:54 2008
New Revision: 4168
URL: http://svn.gnome.org/viewvc/banshee?rev=4168&view=rev
Log:
2008-06-18 Gabriel Burt <gabriel burt gmail com>
First pass at bringing the recommendations extension back. It's got three
big bugs atm: 1) background isn't white 2) height is too small 3) the
similar artist tiles are not sized properly (they're tiny).
* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationActions.cs:
Small class for adding/removing/handling the Show Recommendations action.
* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationService.cs:
Ported from 0.13.2, listens to the source changes and player engine
changes and shows the recommendation pane when appropriate.
* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationPane.cs:
Ported from 0.13.2 but made to use the Lastfm library, shows similar
artists and the top albums and tracks for an artist.
* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs:
Move the TitledList class to not be an inner class; should really be in
its own file.
* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.addin.xml: Update authors,
add recommendations service.
* src/Extensions/Banshee.Lastfm/Banshee.Lastfm.mdp: Add recommendations
source files, and add hyena refs.
* src/Extensions/Banshee.Lastfm/Makefile.am: Add recommendation sources
and resouces.
* src/Extensions/Banshee.Lastfm/Resources/RecommendationMenu.xml: Brought
over verbatim from 0.13.2.
* src/Clients/Nereid/Nereid/PlayerInterface.cs:
* src/Core/Banshee.ThickClient/Banshee.Gui/BaseClientWindow.cs: Add
ViewContainer property so that recommendations can put itself below the
track list.
* src/Core/Banshee.Widgets/Banshee.Widgets/Tile.cs: Add a convenience ctor
for setting the primary text.
* src/Libraries/Lastfm/Lastfm.mdp: Add a bunch of assembly refs.
* src/Libraries/Lastfm/Lastfm.Data/DataEntry.cs: Add a couple missing
properties to the SimilarArtist class.
* src/Libraries/Lastfm/Lastfm.Data/LastfmData.cs: Set the collection this
class backs to a static empty collection until it's loaded its own, so
that the ICollection fucntions will not crash if called before its set.
Move download code into DataCore.
* src/Libraries/Lastfm/Lastfm.Data/DataCore.cs: Moved a bunch of functions
here from LastfmData, and expose a new DownloadContent method so that the
recommendations extension can download cover art and cache it in the
lastfm cache.
* src/Libraries/Lastfm/Lastfm.Data/DataEntryCollection.cs: In the
XmlNodeList ctor, handle the list being null (used by the static
collection mentioned in LastfmData above).
Added:
trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/
trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationActions.cs
trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationPane.cs
trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationService.cs
trunk/banshee/src/Extensions/Banshee.Lastfm/Resources/RecommendationMenu.xml
trunk/banshee/src/Extensions/Banshee.Lastfm/Resources/no-results.png (contents, props changed)
trunk/banshee/src/Extensions/Banshee.Lastfm/ThemeIcons/48x48/
trunk/banshee/src/Extensions/Banshee.Lastfm/ThemeIcons/48x48/generic-artist.png (contents, props changed)
Modified:
trunk/banshee/ChangeLog
trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs
trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/BaseClientWindow.cs
trunk/banshee/src/Core/Banshee.Widgets/Banshee.Widgets/Tile.cs
trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs
trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.addin.xml
trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.mdp
trunk/banshee/src/Extensions/Banshee.Lastfm/Makefile.am
trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataCore.cs
trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataEntry.cs
trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataEntryCollection.cs
trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/LastfmData.cs
trunk/banshee/src/Libraries/Lastfm/Lastfm.mdp
Modified: trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs
==============================================================================
--- trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs (original)
+++ trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs Thu Jun 19 01:20:54 2008
@@ -437,6 +437,10 @@
source_view.ResetHighlight ();
}
+ public override Box ViewContainer {
+ get { return view_container; }
+ }
+
#endregion
#region Gtk.Window Overrides
Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/BaseClientWindow.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/BaseClientWindow.cs (original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/BaseClientWindow.cs Thu Jun 19 01:20:54 2008
@@ -62,6 +62,8 @@
InitializeWindow ();
}
+
+ public abstract Box ViewContainer { get; }
public void ToggleVisibility ()
{
Modified: trunk/banshee/src/Core/Banshee.Widgets/Banshee.Widgets/Tile.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Widgets/Banshee.Widgets/Tile.cs (original)
+++ trunk/banshee/src/Core/Banshee.Widgets/Banshee.Widgets/Tile.cs Thu Jun 19 01:20:54 2008
@@ -41,6 +41,11 @@
private string primary_text;
private string secondary_text;
+
+ public Tile (string primaryText) : base ()
+ {
+ PrimaryText = primaryText;
+ }
public Tile()
{
Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs (original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs Thu Jun 19 01:20:54 2008
@@ -152,26 +152,6 @@
}
}
- public class TitledList : VBox
- {
- private Label title;
-
- public TitledList (string title_str) : base ()
- {
- title = new Label ();
- title.Xalign = 0;
- title.Ellipsize = Pango.EllipsizeMode.End;
- title.Markup = String.Format ("<b>{0}</b>", GLib.Markup.EscapeText (title_str));
-
- PackStart (title, false, false, 0);
- title.Show ();
-
- StyleSet += delegate {
- title.ModifyBg (StateType.Normal, Style.Base (StateType.Normal));
- title.ModifyFg (StateType.Normal, Style.Text (StateType.Normal));
- };
- }
- }
public class NumberedTileView : TileView
{
@@ -286,4 +266,37 @@
}
}
}
+
+ public class TitledList : VBox
+ {
+ private Label title;
+
+ public string Title {
+ get { return title.Text; }
+ set {
+ title.Markup = String.Format ("<b>{0}</b>", GLib.Markup.EscapeText (value));
+ }
+ }
+
+ public int TitleWidthChars {
+ get { return title.WidthChars; }
+ set { title.WidthChars = value; }
+ }
+
+ public TitledList (string title_str) : base (false, 3)
+ {
+ title = new Label ();
+ title.Xalign = 0;
+ title.Ellipsize = Pango.EllipsizeMode.End;
+ Title = title_str;
+
+ PackStart (title, false, false, 0);
+ title.Show ();
+
+ StyleSet += delegate {
+ title.ModifyBg (StateType.Normal, Style.Base (StateType.Normal));
+ title.ModifyFg (StateType.Normal, Style.Text (StateType.Normal));
+ };
+ }
+ }
}
Added: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationActions.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationActions.cs Thu Jun 19 01:20:54 2008
@@ -0,0 +1,92 @@
+//
+// RecommendationActions.cs
+//
+// Authors:
+// Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2007-2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using Gtk;
+
+using Mono.Unix;
+
+using Lastfm;
+using Lastfm.Gui;
+using SortType = Hyena.Data.SortType;
+
+using Banshee.Base;
+using Banshee.Sources;
+using Banshee.Widgets;
+using Banshee.MediaEngine;
+using Banshee.Database;
+using Banshee.Configuration;
+using Banshee.ServiceStack;
+using Banshee.Gui;
+using Banshee.Collection;
+using Banshee.PlaybackController;
+
+using Browser = Banshee.Web.Browser;
+
+namespace Banshee.Lastfm.Recommendations
+{
+ public class RecommendationActions : BansheeActionGroup
+ {
+ private uint actions_id;
+ private RecommendationService service;
+
+ public RecommendationActions (RecommendationService service) : base (ServiceManager.Get<InterfaceActionService> (), "LastfmRecommendations")
+ {
+ this.service = service;
+
+ Add (new ToggleActionEntry [] {
+ new ToggleActionEntry (
+ "ShowRecommendationAction", null,
+ Catalog.GetString("Show Recommendations"), "<control>R",
+ Catalog.GetString("Show Recommendations"), OnToggleShow, true
+ )
+ });
+
+ actions_id = Actions.UIManager.AddUiFromResource ("RecommendationMenu.xml");
+ Actions.AddActionGroup (this);
+ }
+
+ public override void Dispose ()
+ {
+ Actions.UIManager.RemoveUi (actions_id);
+ Actions.RemoveActionGroup (this);
+ base.Dispose ();
+ }
+
+#region Action Handlers
+
+ private void OnToggleShow(object o, EventArgs args)
+ {
+ service.RecommendationsShown = (o as ToggleAction).Active;
+ }
+
+#endregion
+
+ }
+}
Added: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationPane.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationPane.cs Thu Jun 19 01:20:54 2008
@@ -0,0 +1,317 @@
+//
+// RecommendationPane.cs
+//
+// Authors:
+// Fredrik Hedberg
+// Aaron Bockover <aaron abock org>
+// Lukas Lipka
+// Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2005-2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Security.Cryptography;
+
+using Gtk;
+using Mono.Unix;
+
+using Hyena;
+using Hyena.Gui;
+using Hyena.Widgets;
+
+using Lastfm;
+using Lastfm.Data;
+using Lastfm.Gui;
+
+using Banshee.MediaEngine;
+using Banshee.Base;
+using Banshee.Configuration;
+using Banshee.ServiceStack;
+using Banshee.Gui;
+using Banshee.Networking;
+
+using Banshee.Collection;
+using Banshee.Widgets;
+
+using Browser = Lastfm.Browser;
+
+using Banshee.Lastfm.Radio;
+
+namespace Banshee.Lastfm.Recommendations
+{
+ public class RecommendationPane : Hyena.Widgets.RoundedFrame
+ {
+ private HBox main_box;
+ private MessagePane no_artists_pane;
+ private TitledList artist_box;
+ private TitledList album_box;
+ private TitledList track_box;
+
+ private Hyena.Widgets.ScrolledWindow similar_artists_view_sw;
+
+ private TileView similar_artists_view;
+ private VBox album_list;
+ private VBox track_list;
+
+ private object update_sync = new object ();
+
+ private static string album_title_format = Catalog.GetString ("Top Albums by {0}");
+ private static string track_title_format = Catalog.GetString ("Top Tracks by {0}");
+
+ private bool ready = false;
+ private bool show_when_ready = true;
+ public bool ShowWhenReady {
+ get { return show_when_ready; }
+ set {
+ show_when_ready = value;
+ UpdateVisiblity ();
+ }
+ }
+
+ private void UpdateVisiblity ()
+ {
+ if (ShowWhenReady && ready) {
+ ShowAll ();
+ }
+ }
+
+ private string artist;
+ public string Artist {
+ get { return artist; }
+ set {
+ if (artist == value) {
+ UpdateVisiblity ();
+ return;
+ }
+
+ ready = false;
+ if (String.IsNullOrEmpty (value)) {
+ Hide ();
+ return;
+ }
+
+ artist = value;
+ HideWithTimeout ();
+ System.Threading.ThreadPool.QueueUserWorkItem (delegate {
+ lock (update_sync) {
+ UpdateForArtist (artist);
+ }
+ });
+ }
+ }
+
+ public void HideWithTimeout ()
+ {
+ GLib.Timeout.Add (200, OnHideTimeout);
+ }
+
+ private bool OnHideTimeout ()
+ {
+ if (!ShowWhenReady || !ready) {
+ Hide ();
+ }
+ return false;
+ }
+
+ public RecommendationPane () : base ()
+ {
+ //ShadowType = ShadowType.In;
+
+ main_box = new HBox ();
+ main_box.BorderWidth = 5;
+
+ artist_box = new TitledList (String.Format ("Recommended Artists"));
+ similar_artists_view = new TileView (2);
+ similar_artists_view_sw = new Hyena.Widgets.ScrolledWindow ();
+ similar_artists_view_sw.SetPolicy (PolicyType.Automatic, PolicyType.Automatic);
+ similar_artists_view_sw.Add (similar_artists_view);
+ similar_artists_view_sw.ShowAll ();
+ artist_box.PackEnd (similar_artists_view_sw, true, true, 0);
+
+ album_box = new TitledList (null);
+ album_box.TitleWidthChars = 25;
+ album_list = new VBox ();
+ album_box.PackStart (album_list, true, true, 0);
+
+ track_box = new TitledList (null);
+ track_box.TitleWidthChars = 25;
+ track_list = new VBox ();
+ track_box.PackStart (track_list, true, true, 0);
+
+ no_artists_pane = new MessagePane ();
+ no_artists_pane.NoShowAll = true;
+ no_artists_pane.Visible = false;
+ string no_results_message;
+
+ if (!ApplicationContext.Debugging) {
+ no_artists_pane.HeaderIcon = IconThemeUtils.LoadIcon (48, "face-sad", Stock.DialogError);
+ no_results_message = Catalog.GetString("No similar artists found");
+ } else {
+ no_artists_pane.HeaderIcon = Gdk.Pixbuf.LoadFromResource ("no-results.png");
+ no_results_message = "No one likes your music, fool!";
+ }
+
+ no_artists_pane.HeaderMarkup = String.Format ("<big><b>{0}</b></big>", GLib.Markup.EscapeText (no_results_message));
+ artist_box.PackEnd (no_artists_pane, true, true, 0);
+
+ main_box.PackStart (artist_box, true, true, 5);
+ main_box.PackStart (new VSeparator (), false, false, 0);
+ main_box.PackStart (album_box, false, false, 5);
+ main_box.PackStart (new VSeparator (), false, false, 0);
+ main_box.PackStart (track_box, false, false, 5);
+
+ EventBox event_box = new EventBox ();
+
+ /*no_artists_pane.StyleSet += delegate {
+ event_box.ModifyBg (StateType.Normal, no_artists_pane.Style.Base (StateType.Normal));
+ similar_artists_view.ModifyBg (StateType.Normal, no_artists_pane.Style.Base (StateType.Normal));
+ };*/
+
+ /*StyleSet += delegate {
+ ModifyBg (StateType.Normal, Style.Base (StateType.Normal));
+ ModifyFg (StateType.Normal, Style.Text (StateType.Normal));
+ };*/
+
+ event_box.Add (main_box);
+ no_artists_pane.Hide ();
+ Add (event_box);
+ }
+
+ private void UpdateForArtist (string artist_name)
+ {
+ try {
+ LastfmArtistData artist = new LastfmArtistData (artist_name);
+
+ // Make sure all the album art is downloaded
+ foreach (SimilarArtist similar in artist.SimilarArtists) {
+ DataCore.DownloadContent (similar.SmallImageUrl);
+ }
+
+ UpdateForArtist (artist_name, artist.SimilarArtists, artist.TopAlbums, artist.TopTracks);
+ } catch (Exception e) {
+ Log.Exception (e);
+ }
+ }
+
+ private void UpdateForArtist (string artist_name, LastfmData<SimilarArtist> similar_artists, LastfmData<ArtistTopAlbum> top_albums, LastfmData<ArtistTopTrack> top_tracks)
+ {
+ Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+ album_box.Title = String.Format (album_title_format, artist);
+ track_box.Title = String.Format (track_title_format, artist);
+
+ similar_artists_view.ClearWidgets ();
+ ClearBox (album_list);
+ ClearBox (track_list);
+
+ // Similar Artists
+ for (int i = 0; i < Math.Min (20, similar_artists.Count); i++) {
+ SimilarArtist similar_artist = similar_artists[i];
+ Tile tile = new Tile (similar_artist.Name);
+ try {
+ tile.Pixbuf = new Gdk.Pixbuf (DataCore.GetCachedPathFromUrl (similar_artist.SmallImageUrl));
+ } catch {
+ tile.Pixbuf = IconThemeUtils.LoadIcon ("generic-artist", 48);
+ }
+
+ try {
+ tile.SecondaryText = String.Format (Catalog.GetString ("{0}% Similarity"), similar_artist.MatchAsInt);
+ } catch {
+ tile.SecondaryText = Catalog.GetString ("Unknown Similarity");
+ }
+
+ tile.Clicked += delegate { Banshee.Web.Browser.Open (similar_artist.Url); };
+ similar_artists_view.AddWidget (tile);
+ }
+
+ if (similar_artists.Count > 0) {
+ no_artists_pane.Hide ();
+ similar_artists_view_sw.ShowAll ();
+ } else {
+ similar_artists_view_sw.Hide ();
+ no_artists_pane.ShowAll ();
+ }
+
+ for (int i = 0; i < Math.Min (5, top_albums.Count); i++) {
+ ArtistTopAlbum album = top_albums[i];
+ Button album_button = new Button ();
+ album_button.Relief = ReliefStyle.None;
+
+ Label label = new Label ();
+ label.Ellipsize = Pango.EllipsizeMode.End;
+ label.Xalign = 0;
+ label.Markup = String.Format ("{0}. {1}", i+1, GLib.Markup.EscapeText (album.Name));
+ album_button.Add (label);
+
+ album_button.Clicked += delegate {
+ Banshee.Web.Browser.Open (album.Name);
+ };
+ album_list.PackStart (album_button, false, true, 0);
+ }
+ album_box.ShowAll ();
+
+ for (int i = 0; i < Math.Min (5, top_tracks.Count); i++) {
+ ArtistTopTrack track = top_tracks[i];
+ Button track_button = new Button ();
+ track_button.Relief = ReliefStyle.None;
+
+ HBox box = new HBox ();
+
+ Label label = new Label ();
+ label.Ellipsize = Pango.EllipsizeMode.End;
+ label.Xalign = 0;
+ label.Markup = String.Format ("{0}. {1}", i+1, GLib.Markup.EscapeText (track.Name));
+
+ /*if(node.SelectSingleNode("track_id") != null) {
+ box.PackEnd(new Image(now_playing_arrow), false, false, 0);
+ track_button.Clicked += delegate {
+ //PlayerEngineCore.OpenPlay(Globals.Library.GetTrack(
+ //Convert.ToInt32(node.SelectSingleNode("track_id").InnerText)));
+ };
+ } else {*/
+ track_button.Clicked += delegate {
+ Banshee.Web.Browser.Open (track.Url);
+ };
+ //}
+
+ box.PackStart (label, true, true, 0);
+ track_button.Add (box);
+ track_list.PackStart (track_button, false, true, 0);
+ }
+ track_box.ShowAll ();
+
+ ready = true;
+ UpdateVisiblity ();
+ });
+ }
+
+ private static void ClearBox (Box box)
+ {
+ while (box.Children.Length > 0) {
+ box.Remove (box.Children[0]);
+ }
+ }
+ }
+}
Added: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationService.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationService.cs Thu Jun 19 01:20:54 2008
@@ -0,0 +1,160 @@
+//
+// RecommendationService.cs
+//
+// Authors:
+// Aaron Bockover <aaron abock org>
+// Fredrik Hedberg
+// Gabriel Burt <gburt novell com>
+// Lukas Lipka
+//
+// Copyright (C) 2005-2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Security.Cryptography;
+using Gtk;
+using Mono.Unix;
+
+using Hyena;
+
+using Lastfm;
+using Lastfm.Gui;
+
+using Banshee.MediaEngine;
+using Banshee.Base;
+using Banshee.Configuration;
+using Banshee.ServiceStack;
+using Banshee.Gui;
+using Banshee.Networking;
+
+using Banshee.Collection;
+
+using Browser = Lastfm.Browser;
+
+namespace Banshee.Lastfm.Recommendations
+{
+ public class RecommendationService : IExtensionService
+ {
+ private RecommendationPane pane;
+ private RecommendationActions actions;
+
+ void IExtensionService.Initialize ()
+ {
+ pane = new RecommendationPane ();
+
+ BaseClientWindow nereid = ServiceManager.Get<IService> ("NereidPlayerInterface") as Banshee.Gui.BaseClientWindow;
+ if (nereid != null) {
+ nereid.ViewContainer.PackEnd (pane, false, false, 0);
+ }
+
+ actions = new RecommendationActions (this);
+
+ ServiceManager.PlaybackController.SourceChanged += OnSourceChanged;
+ ServiceManager.SourceManager.ActiveSourceChanged += OnActiveSourceChanged;
+ ServiceManager.PlayerEngine.ConnectEvent (OnPlayerEvent, PlayerEvent.StartOfStream | PlayerEvent.EndOfStream);
+ }
+
+ public void Dispose ()
+ {
+ ServiceManager.PlaybackController.SourceChanged -= OnSourceChanged;
+ ServiceManager.SourceManager.ActiveSourceChanged -= OnActiveSourceChanged;
+ ServiceManager.PlayerEngine.DisconnectEvent (OnPlayerEvent);
+
+ if (pane != null) {
+ pane.Destroy ();
+ pane = null;
+ }
+
+ actions.Dispose ();
+ }
+
+ private void OnActiveSourceChanged (EventArgs args)
+ {
+ UpdateVisibility ();
+ }
+
+ private void OnSourceChanged (object sender, EventArgs args)
+ {
+ UpdateVisibility ();
+ }
+
+ private void OnPlayerEvent (PlayerEventArgs args)
+ {
+ TrackInfo track = ServiceManager.PlayerEngine.CurrentTrack;
+ if (track != null) {
+ ShowRecommendations (track.ArtistName);
+ }
+ }
+
+ private void UpdateVisibility ()
+ {
+ bool source_is_playback_source = (ServiceManager.SourceManager.ActiveSource == ServiceManager.PlaybackController.Source);
+ pane.ShowWhenReady = ShowSchema.Get () && source_is_playback_source;
+ if (!source_is_playback_source) {
+ pane.HideWithTimeout ();
+ } else if (!pane.ShowWhenReady) {
+ pane.Hide ();
+ }
+ }
+
+ private void ShowRecommendations (string artist)
+ {
+ lock (this) {
+ if (pane.Visible && pane.Artist == artist) {
+ return;
+ }
+
+ if (!String.IsNullOrEmpty (artist)) {
+ pane.Artist = artist;
+ }
+
+ UpdateVisibility ();
+ }
+ }
+
+ public bool RecommendationsShown {
+ set {
+ ShowSchema.Set (value);
+
+ TrackInfo track = ServiceManager.PlayerEngine.CurrentTrack;
+ if (track != null) {
+ pane.Artist = track.ArtistName;
+ }
+ UpdateVisibility ();
+ }
+ }
+
+ string IService.ServiceName {
+ get { return "LastfmRecommendationService"; }
+ }
+
+ public static readonly SchemaEntry<bool> ShowSchema = new SchemaEntry<bool>(
+ "plugins.recommendation", "show",
+ true,
+ "Show recommendations",
+ "Show recommendations for the currently playing artist"
+ );
+ }
+}
Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.addin.xml
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.addin.xml (original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.addin.xml Thu Jun 19 01:20:54 2008
@@ -7,7 +7,7 @@
name="Last.fm Radio and Scrobbling"
category="User Interface"
description="Provides tightly integrated Last.fm streaming radio and community features."
- author="Gabriel Burt, Alexander Hixon"
+ author="Gabriel Burt, Alexander Hixon, Chris Toshok, Fredrik Hedberg, Aaron Bockover, Lukas Lipka"
url="http://banshee-project.org/"
defaultEnabled="true">
@@ -23,5 +23,9 @@
<Extension path="/Banshee/ServiceManager/Service">
<Service class="Banshee.Lastfm.Audioscrobbler.AudioscrobblerService"/>
</Extension>
+
+ <Extension path="/Banshee/ServiceManager/Service">
+ <Service class="Banshee.Lastfm.Recommendations.RecommendationService"/>
+ </Extension>
</Addin>
Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.mdp
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.mdp (original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.mdp Thu Jun 19 01:20:54 2008
@@ -24,6 +24,10 @@
<File name="Resources/AudioscrobblerMenu.xml" subtype="Code" buildaction="EmbedAsResource" />
<File name="Banshee.Lastfm.Radio/LastfmColumnController.cs" subtype="Code" buildaction="Compile" />
<File name="Resources/LastfmTrackActions.xml" subtype="Code" buildaction="EmbedAsResource" />
+ <File name="Banshee.Lastfm.Recommendations/RecommendationActions.cs" subtype="Code" buildaction="Compile" />
+ <File name="Banshee.Lastfm.Recommendations/RecommendationPane.cs" subtype="Code" buildaction="Compile" />
+ <File name="Banshee.Lastfm.Recommendations/RecommendationService.cs" subtype="Code" buildaction="Compile" />
+ <File name="Resources/RecommendationMenu.xml" subtype="Code" buildaction="EmbedAsResource" />
</Contents>
<References>
<ProjectReference type="Gac" localcopy="True" refto="gtk-sharp, Version=2.8.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
@@ -39,6 +43,8 @@
<ProjectReference type="Project" localcopy="True" refto="Banshee.Core" />
<ProjectReference type="Project" localcopy="True" refto="Banshee.Services" />
<ProjectReference type="Project" localcopy="True" refto="Banshee.ThickClient" />
+ <ProjectReference type="Project" localcopy="True" refto="Hyena" />
+ <ProjectReference type="Project" localcopy="True" refto="Hyena.Gui" />
</References>
<MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="True" RelativeMakefileName="Makefile.am">
<BuildFilesVar Sync="True" Name="SOURCES" />
Modified: trunk/banshee/src/Extensions/Banshee.Lastfm/Makefile.am
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Lastfm/Makefile.am (original)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Makefile.am Thu Jun 19 01:20:54 2008
@@ -13,7 +13,11 @@
Banshee.Lastfm.Radio/LastfmTrackInfo.cs \
Banshee.Lastfm.Radio/StationEditor.cs \
Banshee.Lastfm.Radio/StationSource.cs \
- Banshee.Lastfm.Radio/StationType.cs
+ Banshee.Lastfm.Radio/StationType.cs \
+ Banshee.Lastfm.Recommendations/RecommendationActions.cs \
+ Banshee.Lastfm.Recommendations/RecommendationPane.cs \
+ Banshee.Lastfm.Recommendations/RecommendationService.cs
+
RESOURCES = \
Banshee.Lastfm.addin.xml \
@@ -21,7 +25,9 @@
Resources/AudioscrobblerMenu.xml \
Resources/GlobalUI.xml \
Resources/lastfm.glade \
- Resources/LastfmTrackActions.xml
+ Resources/LastfmTrackActions.xml \
+ Resources/RecommendationMenu.xml \
+ Resources/no-results.png
include $(top_srcdir)/build/build.mk
Added: trunk/banshee/src/Extensions/Banshee.Lastfm/Resources/RecommendationMenu.xml
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Extensions/Banshee.Lastfm/Resources/RecommendationMenu.xml Thu Jun 19 01:20:54 2008
@@ -0,0 +1,9 @@
+<ui>
+ <menubar name="MainMenu">
+ <menu name="ViewMenu" action="ViewMenuAction">
+ <placeholder name="ViewMenuAdditions">
+ <menuitem name="ShowRecommendation" action="ShowRecommendationAction" />
+ </placeholder>
+ </menu>
+ </menubar>
+</ui>
Added: trunk/banshee/src/Extensions/Banshee.Lastfm/Resources/no-results.png
==============================================================================
Binary file. No diff available.
Added: trunk/banshee/src/Extensions/Banshee.Lastfm/ThemeIcons/48x48/generic-artist.png
==============================================================================
Binary file. No diff available.
Modified: trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataCore.cs
==============================================================================
--- trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataCore.cs (original)
+++ trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataCore.cs Thu Jun 19 01:20:54 2008
@@ -2,7 +2,10 @@
// DataCore.cs
//
// Authors:
-// Gabriel Burt <gburt novell com>
+// Gabriel Burt
+// Fredrik Hedberg
+// Aaron Bockover
+// Lukas Lipka
//
// Copyright (C) 2008 Novell, Inc.
//
@@ -28,6 +31,12 @@
using System;
using System.IO;
+using System.Net;
+using System.Web;
+using System.Xml;
+using System.Collections;
+using System.Collections.Generic;
+using ICSharpCode.SharpZipLib.GZip;
using Hyena;
@@ -55,6 +64,85 @@
SetupCache();
}
}
+
+ public static string DownloadContent (string data_url)
+ {
+ return DownloadContent (data_url, CacheDuration.Infinite);
+ }
+
+ public static string DownloadContent (string data_url, CacheDuration cache_duration)
+ {
+ return DownloadContent (data_url, GetCachedPathFromUrl (data_url), cache_duration);
+ }
+
+ internal static string DownloadContent (string data_url, string cache_file, CacheDuration cache_duration)
+ {
+ data_url = FixLastfmUrl (data_url);
+ // See if we have a valid cached copy
+ if (cache_duration != CacheDuration.None) {
+ if (File.Exists (cache_file)) {
+ DateTime last_updated_time = File.GetLastWriteTime (cache_file);
+ if (cache_duration == CacheDuration.Infinite || DateTime.Now - last_updated_time < DataCore.NormalCacheTime) {
+ return cache_file;
+ }
+ }
+ }
+
+ HttpWebRequest request = (HttpWebRequest) WebRequest.Create (data_url);
+ request.UserAgent = DataCore.UserAgent;
+ request.KeepAlive = false;
+
+ using (HttpWebResponse response = (HttpWebResponse) request.GetResponse ()) {
+ using (Stream stream = GetResponseStream (response)) {
+ using (FileStream file_stream = File.Open (cache_file, FileMode.Create)) {
+ using (BufferedStream buffered_stream = new BufferedStream (file_stream)) {
+ byte [] buffer = new byte[8192];
+ int read;
+
+ while (true) {
+ read = stream.Read (buffer, 0, buffer.Length);
+ if (read <= 0) {
+ break;
+ }
+
+ buffered_stream.Write (buffer, 0, read);
+ }
+ }
+ }
+ }
+ }
+ return cache_file;
+ }
+
+
+ public static string GetCachedPathFromUrl (string url)
+ {
+ string hash = FixLastfmUrl (url).GetHashCode ().ToString ("X").ToLower ();
+ return Path.Combine (Path.Combine (DataCore.CachePath, hash.Substring (0, 2)), hash);
+ }
+
+ private static Stream GetResponseStream (HttpWebResponse response)
+ {
+ return response.ContentEncoding == "gzip"
+ ? new GZipInputStream (response.GetResponseStream ())
+ : response.GetResponseStream ();
+ }
+
+ // FIXME: This is to (try to) work around a bug in last.fm's XML
+ // Some XML nodes with URIs as content do not return a URI with a
+ // host name. It appears that in these cases the hostname is to be
+ // static3.last.fm, but it may not always be the case - this is
+ // a bug in last.fm, but we attempt to work around it here
+ // http://bugzilla.gnome.org/show_bug.cgi?id=408068
+
+ internal static string FixLastfmUrl (string url)
+ {
+ if (url.StartsWith ("http:///storable/")) {
+ url = url.Insert (7, "static3.last.fm");
+ }
+
+ return url;
+ }
private static void SetupCache()
{
Modified: trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataEntry.cs
==============================================================================
--- trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataEntry.cs (original)
+++ trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataEntry.cs Thu Jun 19 01:20:54 2008
@@ -191,6 +191,8 @@
// Artist entries
public class SimilarArtist : NamedEntry
{
+ public string ImageUrl { get { return Get<string> ("image"); } }
+ public string SmallImageUrl { get { return Get<string> ("image_small"); } }
public double Match { get { return Get<double> ("match"); } }
public int MatchAsInt { get { return (int) Math.Round (Match); } }
}
Modified: trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataEntryCollection.cs
==============================================================================
--- trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataEntryCollection.cs (original)
+++ trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/DataEntryCollection.cs Thu Jun 19 01:20:54 2008
@@ -49,7 +49,7 @@
public DataEntryCollection (XmlNodeList nodes)
{
this.nodes = nodes;
- count = nodes.Count;
+ count = nodes == null ? 0 : nodes.Count;
}
public int Count {
Modified: trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/LastfmData.cs
==============================================================================
--- trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/LastfmData.cs (original)
+++ trunk/banshee/src/Libraries/Lastfm/Lastfm.Data/LastfmData.cs Thu Jun 19 01:20:54 2008
@@ -2,7 +2,10 @@
// LastfmData.cs
//
// Authors:
-// Gabriel Burt <gburt novell com>
+// Gabriel Burt
+// Fredrik Hedberg
+// Aaron Bockover
+// Lukas Lipka
//
// Copyright (C) 2008 Novell, Inc.
//
@@ -48,7 +51,8 @@
public class LastfmData<T> : IEnumerable<T> where T : DataEntry
{
- protected DataEntryCollection<T> collection;
+ private static DataEntryCollection<T> empty_collection = new DataEntryCollection<T> ((XmlNodeList)null);
+ protected DataEntryCollection<T> collection = empty_collection;
protected XmlDocument doc;
protected string data_url;
protected string cache_file;
@@ -71,8 +75,8 @@
{
DataCore.Initialize ();
- this.data_url = HostInjectionHack (String.Format ("http://ws.audioscrobbler.com/1.0/{0}", dataUrlFragment));
- this.cache_file = GetCachedPathFromUrl (data_url);
+ this.data_url = DataCore.FixLastfmUrl (String.Format ("http://ws.audioscrobbler.com/1.0/{0}", dataUrlFragment));
+ this.cache_file = DataCore.GetCachedPathFromUrl (data_url);
this.cache_duration = cacheDuration;
this.xpath = xpath;
@@ -90,7 +94,7 @@
private void GetData ()
{
// Download the content if necessary
- DownloadContent ();
+ DataCore.DownloadContent (data_url, cache_file, cache_duration);
// Load the XML from the new or cached local file
doc = new XmlDocument ();
@@ -133,73 +137,6 @@
#region Private methods
- private void DownloadContent ()
- {
- // See if we have a valid cached copy
- if (cache_duration != CacheDuration.None) {
- if (File.Exists (cache_file)) {
- DateTime last_updated_time = File.GetLastWriteTime (cache_file);
- if (cache_duration == CacheDuration.Infinite || DateTime.Now - last_updated_time < DataCore.NormalCacheTime) {
- return;
- }
- }
- }
-
- HttpWebRequest request = (HttpWebRequest) WebRequest.Create (data_url);
- request.UserAgent = DataCore.UserAgent;
- request.KeepAlive = false;
-
- using (HttpWebResponse response = (HttpWebResponse) request.GetResponse ()) {
- using (Stream stream = GetResponseStream (response)) {
- using (FileStream file_stream = File.Open (cache_file, FileMode.Create)) {
- using (BufferedStream buffered_stream = new BufferedStream (file_stream)) {
- byte [] buffer = new byte[8192];
- int read;
-
- while (true) {
- read = stream.Read (buffer, 0, buffer.Length);
- if (read <= 0) {
- break;
- }
-
- buffered_stream.Write (buffer, 0, read);
- }
- }
- }
- }
- }
- }
-
- private static Stream GetResponseStream (HttpWebResponse response)
- {
- return response.ContentEncoding == "gzip"
- ? new GZipInputStream (response.GetResponseStream ())
- : response.GetResponseStream ();
- }
-
-
- private static string GetCachedPathFromUrl (string url)
- {
- string hash = url.GetHashCode ().ToString ("X").ToLower ();
- return Path.Combine (Path.Combine (DataCore.CachePath, hash.Substring (0, 2)), hash);
- }
-
- // FIXME: This is to (try to) work around a bug in last.fm's XML
- // Some XML nodes with URIs as content do not return a URI with a
- // host name. It appears that in these cases the hostname is to be
- // static3.last.fm, but it may not always be the case - this is
- // a bug in last.fm, but we attempt to work around it here
- // http://bugzilla.gnome.org/show_bug.cgi?id=408068
-
- private static string HostInjectionHack (string url)
- {
- if (url.StartsWith ("http:///storable/")) {
- url = url.Insert (7, "static3.last.fm");
- }
-
- return url;
- }
-
#endregion
}
Modified: trunk/banshee/src/Libraries/Lastfm/Lastfm.mdp
==============================================================================
--- trunk/banshee/src/Libraries/Lastfm/Lastfm.mdp (original)
+++ trunk/banshee/src/Libraries/Lastfm/Lastfm.mdp Thu Jun 19 01:20:54 2008
@@ -29,5 +29,9 @@
<ProjectReference type="Project" localcopy="True" refto="Mono.Media" />
<ProjectReference type="Gac" localcopy="True" refto="ICSharpCode.SharpZipLib, Version=2.84.0.0, Culture=neutral, PublicKeyToken=1b03e6acf1164f73" />
<ProjectReference type="Gac" localcopy="True" refto="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+ <ProjectReference type="Gac" localcopy="True" refto="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <ProjectReference type="Gac" localcopy="True" refto="Hyena, Version=1.0.1.17734, Culture=neutral, PublicKeyToken=null" />
+ <ProjectReference type="Gac" localcopy="True" refto="Hyena.Gui, Version=1.0.1.17735, Culture=neutral, PublicKeyToken=null" />
</References>
</Project>
\ No newline at end of file
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]