[banshee/amazon] Amazon pane starting to be functional. Will show top tracks and albums for the playing song, with o



commit 39832c8ca406eda3bfbc9a2c9cba5d25f04cb1cc
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Fri May 8 14:13:52 2009 -0500

    Amazon pane starting to be functional.  Will show top tracks and albums for the playing song, with options to play preview and go to Amazon.com details/purchase page for each item.   Moved TitltedList out of Banshee.Lastfm, and added override for Banshee.Web.Browser.Open to say if the url has already been escaped
---
 src/Core/Banshee.Services/Banshee.Web/Browser.cs   |   12 +-
 .../Banshee.Gui.Widgets/ContextPane.cs             |   10 +-
 .../Banshee.Gui.Widgets/TitledList.cs              |   67 +++++++
 .../Banshee.ThickClient/Banshee.ThickClient.csproj |    1 +
 src/Core/Banshee.ThickClient/Makefile.am           |    1 +
 .../Banshee.Amazon/Banshee.Amazon.addin.xml        |    6 +-
 .../Banshee.Amazon/Banshee.Amazon.csproj           |   18 ++-
 .../Banshee.Amazon/Banshee.Amazon/AmazonActions.cs |   51 +++++
 .../Banshee.Amazon/Banshee.Amazon/AmazonPane.cs    |  200 ++++++++++++++++++++
 .../Banshee.Amazon/AmazonPreviewTrackInfo.cs       |   19 ++
 .../Banshee.Amazon/Banshee.Amazon/AmazonTest.cs    |   83 +++++++--
 .../Banshee.Amazon/Banshee.Amazon/AmazonUtils.cs   |  125 ++++++++++++
 src/Extensions/Banshee.Amazon/Makefile.am          |   10 +-
 .../Banshee.Amazon/Resources/GlobalUI.xml          |    7 +
 .../ThemeIcons/16x16/categories/amazon.png         |  Bin 0 -> 677 bytes
 .../ThemeIcons/22x22/categories/amazon.png         |  Bin 0 -> 870 bytes
 .../ThemeIcons/24x24/categories/amazon.png         |  Bin 0 -> 894 bytes
 .../Banshee.Lastfm.Radio/LastfmSourceContents.cs   |   32 +---
 .../RecommendationPane.cs                          |    1 +
 19 files changed, 587 insertions(+), 56 deletions(-)

diff --git a/src/Core/Banshee.Services/Banshee.Web/Browser.cs b/src/Core/Banshee.Services/Banshee.Web/Browser.cs
index e9c5630..8fd26e0 100644
--- a/src/Core/Banshee.Services/Banshee.Web/Browser.cs
+++ b/src/Core/Banshee.Services/Banshee.Web/Browser.cs
@@ -46,11 +46,19 @@ namespace Banshee.Web
             get { return open_handler; }
             set { open_handler = value; }
         }
-    
+
         public static bool Open (string url)
         {
+            return Open (url, false);
+        }
+    
+        public static bool Open (string url, bool alreadyEscaped)
+        {
             try {
-                url = Uri.EscapeUriString (url);
+                if (!alreadyEscaped) {
+                    url = Uri.EscapeUriString (url);
+                }
+
                 if (open_handler != null) {
                     return open_handler (url);
                 } else {
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ContextPane.cs b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ContextPane.cs
index 533b2eb..8affee8 100644
--- a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ContextPane.cs
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ContextPane.cs
@@ -60,6 +60,7 @@ namespace Banshee.Gui.Widgets
 
         private void OnExtensionChanged (object o, ExtensionNodeEventArgs args) 
         {
+            Hyena.Log.InformationFormat ("Got contextPanePage node {0}", args.Path);
             TypeExtensionNode node = (TypeExtensionNode)args.ExtensionNode;
             var page = (ContextPanePage) (node.GetInstance () ?? node.CreateInstance ());
             
@@ -81,7 +82,7 @@ namespace Banshee.Gui.Widgets
         private RadioButton radio_group = new RadioButton (null, "");
 
         private Dictionary<ContextPanePage, RadioButton> pane_tabs = new Dictionary<ContextPanePage, RadioButton> ();
-        //private Dictionary<
+        private Dictionary<ContextPanePage, Widget> pane_pages = new Dictionary<ContextPanePage, Widget> ();
         
         public ContextPane ()
         {
@@ -105,11 +106,13 @@ namespace Banshee.Gui.Widgets
 
         public void AddPage (ContextPanePage page)
         {
+            Hyena.Log.DebugFormat ("Adding context page {0}", page.Id);
             var frame = new Hyena.Widgets.RoundedFrame ();
             frame.Add (page.Widget);
             frame.Show ();
             page.Widget.Show ();
             notebook.AppendPage (frame, null);
+            pane_pages[page] = frame;
 
             var tab_image = new Image (IconThemeUtils.LoadIcon (22, page.IconNames));
             var toggle_button = new RadioButton (radio_group) {
@@ -117,7 +120,7 @@ namespace Banshee.Gui.Widgets
                 DrawIndicator = false
             };
             toggle_button.Relief = ReliefStyle.None;
-            toggle_button.Clicked += (s, e) => notebook.CurrentPage = notebook.PageNum (page.Widget);
+            toggle_button.Clicked += (s, e) => notebook.CurrentPage = notebook.PageNum (pane_pages[page]);
             
             TooltipSetter.Set (tooltip_host, toggle_button, page.Name);
 
@@ -132,9 +135,10 @@ namespace Banshee.Gui.Widgets
 
         public void RemovePage (ContextPanePage page)
         {
-            notebook.RemovePage (notebook.PageNum (page.Widget));
+            notebook.RemovePage (notebook.PageNum (pane_pages[page]));
             vbox.Remove (pane_tabs[page]);
             pane_tabs.Remove (page);
+            pane_pages.Remove (page);
         }
     }
 }
diff --git a/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TitledList.cs b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TitledList.cs
new file mode 100644
index 0000000..afc9e92
--- /dev/null
+++ b/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/TitledList.cs
@@ -0,0 +1,67 @@
+//
+// TitledList.cs
+//
+// Authors:
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 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 Gtk;
+
+namespace Banshee.Gui.Widgets
+{
+    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));
+            };
+        }
+    }
+}
diff --git a/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj b/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj
index b14d088..006334e 100644
--- a/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj
+++ b/src/Core/Banshee.ThickClient/Banshee.ThickClient.csproj
@@ -229,6 +229,7 @@
     <Compile Include="Banshee.Preferences.Gui\PageComboBox.cs" />
     <Compile Include="Banshee.Gui.TrackEditor\LicenseEntry.cs" />
     <Compile Include="Banshee.Gui.Widgets\ContextPane.cs" />
+    <Compile Include="Banshee.Gui.Widgets\TitledList.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>
diff --git a/src/Core/Banshee.ThickClient/Makefile.am b/src/Core/Banshee.ThickClient/Makefile.am
index 845b261..8afe5f0 100644
--- a/src/Core/Banshee.ThickClient/Makefile.am
+++ b/src/Core/Banshee.ThickClient/Makefile.am
@@ -92,6 +92,7 @@ SOURCES =  \
 	Banshee.Gui.Widgets/PlaylistMenuItem.cs \
 	Banshee.Gui.Widgets/RepeatActionButton.cs \
 	Banshee.Gui.Widgets/TaskStatusIcon.cs \
+	Banshee.Gui.Widgets/TitledList.cs \
 	Banshee.Gui.Widgets/TrackInfoDisplay.cs \
 	Banshee.Gui.Widgets/UserJobTile.cs \
 	Banshee.Gui.Widgets/UserJobTileHost.cs \
diff --git a/src/Extensions/Banshee.Amazon/Banshee.Amazon.addin.xml b/src/Extensions/Banshee.Amazon/Banshee.Amazon.addin.xml
index 67b5813..ab83083 100644
--- a/src/Extensions/Banshee.Amazon/Banshee.Amazon.addin.xml
+++ b/src/Extensions/Banshee.Amazon/Banshee.Amazon.addin.xml
@@ -9,7 +9,7 @@
     description="Access Amazon production information, your cart, and wishlists from within Banshee."
     author="Gabriel Burt"
     url="http://banshee-project.org/";
-    defaultEnabled="false">
+    defaultEnabled="true">
 
   <Dependencies>
     <Addin id="Banshee.Services" version="1.0"/>
@@ -19,5 +19,9 @@
   <Extension path="/Banshee/ServiceManager/Service">
     <Service class="Banshee.Amazon.AmazonTest"/>
   </Extension>
+
+  <Extension path="/Banshee/ThickClient/ContextPanePage">
+    <ContextPanePage class="Banshee.Amazon.AmazonPane"/>
+  </Extension>
   
 </Addin>
diff --git a/src/Extensions/Banshee.Amazon/Banshee.Amazon.csproj b/src/Extensions/Banshee.Amazon/Banshee.Amazon.csproj
index d0a8654..a2ecf49 100644
--- a/src/Extensions/Banshee.Amazon/Banshee.Amazon.csproj
+++ b/src/Extensions/Banshee.Amazon/Banshee.Amazon.csproj
@@ -31,22 +31,25 @@
   </ItemGroup>
   <ProjectExtensions>
     <MonoDevelop>
-      <Properties>
+      <Properties InternalTargetFrameworkVersion="3.5">
         <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="true" RelativeMakefileName="Makefile.am" IsAutotoolsProject="true" RelativeConfigureInPath="../../..">
-          <BuildFilesVar />
+          <BuildFilesVar Sync="true" Name="SOURCES" />
           <DeployFilesVar />
           <ResourcesVar Sync="true" Name="RESOURCES" />
           <OthersVar />
           <GacRefVar />
           <AsmRefVar />
           <ProjectRefVar />
-          <MessageRegex Name="Vala" />
         </MonoDevelop.Autotools.MakefileInfo>
       </Properties>
     </MonoDevelop>
   </ProjectExtensions>
   <ItemGroup>
     <Compile Include="Banshee.Amazon\AmazonTest.cs" />
+    <Compile Include="Banshee.Amazon\AmazonPane.cs" />
+    <Compile Include="Banshee.Amazon\AmazonUtils.cs" />
+    <Compile Include="Banshee.Amazon\AmazonPreviewTrackInfo.cs" />
+    <Compile Include="Banshee.Amazon\AmazonActions.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\Libraries\amazon-ecs-2007-07-16-cs-library\src\Amazon.ECS\Amazon.ECS.csproj">
@@ -74,4 +77,13 @@
       <Name>Hyena.Gui</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <Reference Include="Mono.Posix" />
+    <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+    <Reference Include="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+    <Reference Include="System.Core" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Resources\GlobalUI.xml" />
+  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonActions.cs b/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonActions.cs
new file mode 100644
index 0000000..b579e1f
--- /dev/null
+++ b/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonActions.cs
@@ -0,0 +1,51 @@
+
+using System;
+
+using Mono.Unix;
+
+using Gtk;
+
+using Banshee.Gui;
+using Banshee.MediaEngine;
+using Banshee.ServiceStack;
+
+namespace Banshee.Amazon
+{
+    public class AmazonActions : BansheeActionGroup
+    {
+        public AmazonActions () : base ("amazon")
+        {
+            AddImportant (
+                new ActionEntry (
+                    "AmazonDetailsAction", Stock.JumpTo,
+                     Catalog.GetString ("_Buy on Amazon..."),
+                     null, Catalog.GetString ("Open the details and purchase page for this track on Amazon.com"), OnAmazonDetails
+                )
+            );
+
+            AddUiFromFile ("GlobalUI.xml");
+            Register ();
+
+            ServiceManager.PlayerEngine.ConnectEvent (OnPlayerEvent, PlayerEvent.StartOfStream | PlayerEvent.EndOfStream);
+            OnPlayerEvent (null);
+        }
+
+        private AmazonPreviewTrackInfo AmazonTrack {
+            get { return ServiceManager.PlayerEngine.CurrentTrack as AmazonPreviewTrackInfo; }
+        }
+
+        private void OnPlayerEvent (object args)
+        {
+            // Only show when playing an amazon preview track
+            UpdateAction ("AmazonDetailsAction", AmazonTrack != null, true);
+        }
+
+        private void OnAmazonDetails (object o, EventArgs args)
+        {
+            var amazon_track = AmazonTrack;
+            if (amazon_track != null) {
+                Banshee.Web.Browser.Open (amazon_track.Item.DetailPageURL, true);
+            }
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonPane.cs b/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonPane.cs
new file mode 100644
index 0000000..73805e1
--- /dev/null
+++ b/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonPane.cs
@@ -0,0 +1,200 @@
+
+using System;
+using System.Linq;
+
+using Mono.Unix;
+
+using Gtk;
+
+using Hyena.Widgets;
+
+using Banshee.Gui.Widgets;
+using Banshee.MediaEngine;
+using Banshee.Collection;
+using Banshee.ServiceStack;
+using AMZN = Amazon.ECS.Model;
+
+namespace Banshee.Amazon
+{
+    public class AmazonPane : ContextPanePage
+    {
+        public AmazonPane ()
+        {
+            Id = "amazon";
+            Name = Catalog.GetString ("Amazon Recommendations");
+            IconNames = new string[] { "amazon", "audio-x-generic" };
+
+            ServiceManager.PlayerEngine.ConnectEvent (OnPlayerEvent, PlayerEvent.StartOfStream | PlayerEvent.TrackInfoUpdated);
+
+            new AmazonActions ();
+        }
+
+        private void OnPlayerEvent (object args)
+        {
+            TrackInfo track = ServiceManager.PlayerEngine.CurrentTrack;
+            if (track != null) {
+                Banshee.Base.ThreadAssist.SpawnFromMain (delegate {
+                    widget.UpdateForTrack (track);
+                });
+            }
+        }
+
+        private AmazonRecs widget = new AmazonRecs ();
+        public override Widget Widget {
+            get { return widget; }
+        }
+    }
+
+    public class AmazonRecs : HBox
+    {
+        AMZN.Cart cart;
+
+        TitledList album_box;
+        VBox album_list;
+        Gtk.ScrolledWindow album_sw;
+        
+        TitledList track_box;
+        VBox track_list;
+        Gtk.ScrolledWindow track_sw;
+
+        public AmazonRecs ()
+        {
+            album_box  = new TitledList ("Top Albums");
+            album_box.TitleWidthChars = 35;
+            album_box.SizeAllocated += OnSideSizeAllocated;
+            album_list = new VBox ();
+            album_sw = new Gtk.ScrolledWindow ();
+            album_sw.SetPolicy (PolicyType.Never, PolicyType.Automatic);
+            album_sw.AddWithViewport (album_box);
+            album_box.PackStart (album_list, false, false, 0);
+
+            track_box  = new TitledList ("Top Tracks");
+            track_box.SizeAllocated += OnSideSizeAllocated;
+            track_box.TitleWidthChars = 35;
+            track_list = new VBox ();
+            track_sw = new Gtk.ScrolledWindow ();
+            track_sw.SetPolicy (PolicyType.Never, PolicyType.Automatic);
+            track_sw.AddWithViewport (track_box);
+            track_box.PackStart (track_list, true, true, 0);
+            
+            PackStart (album_sw, true, true, 5);
+            PackStart (new VSeparator (), false, false, 0);
+            PackStart (track_sw, true, true, 5);
+
+            ShowAll ();
+        }
+
+        private void OnSideSizeAllocated (object o, SizeAllocatedArgs args)
+        {
+            //SetSizeRequest (-1, args.Allocation.Height + (Allocation.Height - args.Allocation.Height));
+        }
+
+        protected override void OnStyleSet (Style previous_style)
+        {
+            base.OnStyleSet (previous_style);
+            album_sw.ModifyBg (StateType.Normal, Style.Base (StateType.Normal));
+            track_sw.ModifyBg (StateType.Normal, Style.Base (StateType.Normal));
+        }
+
+        string last_artist;
+        public void UpdateForTrack (TrackInfo track)
+        {
+            if (track.ArtistName == last_artist)
+                return;
+
+            last_artist = track.ArtistName;
+            var albums = AmazonUtils.FindItems (track.ArtistName, true, false);
+            var tracks = AmazonUtils.FindItems (track.ArtistName, true, true);
+            Hyena.Log.DebugFormat ("Got amazon items for {0}", track.ArtistName);
+
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                while (album_list.Children.Length > 0)
+                    album_list.Remove (album_list.Children[0]);
+
+                album_box.Title = String.Format (Catalog.GetString ("Top Albums by {0}"), track.ArtistName);
+                foreach (var item in albums) {
+                    Console.WriteLine ("Got item {0}", item.ItemAttributes.Title);
+                    album_list.PackEnd (CreateItemWidget (item), false, false, 0);
+                }
+
+                while (track_list.Children.Length > 0)
+                    track_list.Remove (track_list.Children[0]);
+
+                track_box.Title = String.Format (Catalog.GetString ("Top Tracks by {0}"), track.ArtistName);
+                foreach (var item in tracks) {
+                    Console.WriteLine ("Got item {0}", item.ItemAttributes.Title);
+                    track_list.PackEnd (CreateItemWidget (item), false, false, 0);
+                }
+    
+                ShowAll ();
+            });
+        }
+
+        private Widget CreateItemWidget (AMZN.Item item)
+        {
+            var label = new Label ();
+            label.Xalign = 0;
+            label.Ellipsize = Pango.EllipsizeMode.End;
+            label.Markup = String.Format ("{0} ({1})", item.ItemAttributes.Title, item.OfferSummary.LowestNewPrice.FormattedPrice);
+
+            //var play_btn = new Button (new Image (Banshee.Gui.IconThemeUtils.LoadIcon ("media-playback-start", 16))) { Relief = ReliefStyle.None };
+            //var add_btn = new Button (new Image (Banshee.Gui.IconThemeUtils.LoadIcon (Stock.Add, 16))) { Relief = ReliefStyle.None };
+
+            var hbox = new HBox ();
+            hbox.Spacing = 5;
+            hbox.PackStart (label, true, true, 0);
+            //hbox.PackStart (add_btn, false, false, 0);
+            //hbox.PackStart (play_btn, false, false, 0);
+
+            var widget = new MenuButton (hbox, CreateMenu (item), true);
+            widget.Name = item.ItemAttributes.Title;
+            widget.CanFocus = true;
+            
+            return widget;
+        }
+
+        private Menu CreateMenu (AMZN.Item item)
+        {
+            //asin = "B001RTP3YQ";
+            //asin = "B0012EJVIA"; // mp3 album
+            string asin = item.ASIN;
+            Menu menu = new Menu ();
+
+            var goto_details = new ImageMenuItem (Catalog.GetString ("Buy on Amazon..."));
+            goto_details.Image = new Image (Stock.JumpTo, IconSize.Menu);
+            goto_details.Activated += (o, a) => {
+                Banshee.Web.Browser.Open (item.DetailPageURL, true);
+            };
+
+            var queue_preview = new ImageMenuItem (Catalog.GetString ("Play Preview"));
+            queue_preview.Image = new Image (Banshee.Gui.IconThemeUtils.LoadIcon ("media-playback-start", (int)IconSize.Menu));
+            queue_preview.Activated += (o, a) => {
+                new AmazonPreviewTrackInfo (item).Play ();
+            };
+
+            var add_to_cart = new ImageMenuItem (Catalog.GetString ("Add to Cart"));
+            add_to_cart.Image = new Image (Stock.Add, IconSize.Menu);
+            add_to_cart.Activated += (o, a) => {
+                Console.WriteLine ("Got add to cart for asin {0}", asin);
+                if (cart == null) {
+                    cart = AmazonUtils.CreateCart (asin);
+                } else {
+                    AmazonUtils.AddToCart (cart, asin);
+                }
+
+                Console.WriteLine ("Have cart purchaseURL = {0}", cart.PurchaseURL);
+            };
+
+            menu.Append (goto_details);
+            menu.Append (queue_preview);
+
+            // Unfortunately, the Amazon API doesn't let you add mp3 tracks or albums to the cart
+            // See http://developer.amazonwebservices.com/connect/thread.jspa?messageID=121497&#121497
+            if (item.ItemAttributes.Binding != "MP3 Download") {
+                menu.Append (add_to_cart);
+            }
+            menu.ShowAll ();
+            return menu;
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonPreviewTrackInfo.cs b/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonPreviewTrackInfo.cs
new file mode 100644
index 0000000..13c2358
--- /dev/null
+++ b/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonPreviewTrackInfo.cs
@@ -0,0 +1,19 @@
+
+using System;
+
+using Banshee.Base;
+using Banshee.Streaming;
+using AMZN = Amazon.ECS.Model;
+
+namespace Banshee.Amazon
+{
+    public class AmazonPreviewTrackInfo : Banshee.Streaming.RadioTrackInfo
+    {
+        public AMZN.Item Item { get; private set; }
+
+        public AmazonPreviewTrackInfo (AMZN.Item item) : base (new Banshee.Base.SafeUri (AmazonUtils.PreviewPlaylistUrl (item.ASIN)))
+        {
+            Item = item;
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonTest.cs b/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonTest.cs
index cfe3b50..7d7ec4d 100644
--- a/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonTest.cs
+++ b/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonTest.cs
@@ -11,6 +11,7 @@ namespace Banshee.Amazon
     {
         private const string ACCESS_KEY = "1WX2TV6EWH519QW2V482";
         private const string AFFILIATE_TAG = "banshee";
+        private const string PREVIEW_URL_FMT = "http://www.amazon.com/gp/dmusic/media/sample.m3u/ref=dm_sp_smpl?ie=UTF8&catalogItemType=track&ASIN={0}";;
 
         private AmazonECSQuery service;
 
@@ -43,42 +44,96 @@ namespace Banshee.Amazon
             public const string DigitalMusicPerformer = "";
             public const string DidigtalPrimaryArtist = "";
             public const string Tracks = "";
-        }
+        }*/
 
         public void FindItems ()
         {
+            //ItemLookupRequest
             ItemSearchRequest request = new ItemSearchRequest ();
-            request.SearchIndex = "Music";
-            request.Artist = "Bob Dylan";
-            //request.Conductor
-            //request.Composer
-            //request.WithKeywords
-            request.WithSearchIndex (SearchIn
+            request.SearchIndex = "MP3Downloads"; //"DigitalMusic"; //"Music";
+            request.Author = "Bob Dylan";
+            //request.WithRelationshipType ("Tracks");
+            request.WithResponseGroup ("Large", "Tags", "Tracks", "Reviews");//, "RelatedItems");
 
             try {
                 ItemSearchResponse response = service.ItemSearch (request);
-                Hyena.Log.Information ("Got response to Amazon query", response.ToXML ());
+                System.IO.File.WriteAllText ("amazon-bob_dylan-search.xml", response.ToXML ());
             } catch (AmazonECSException e) {
                 Hyena.Log.Exception (e);
             }
-
-            RelationshipTypes = "Tracks", 
-        }*/
+        }
 
         public void FindSimilar (string item_id)
         {
             var request = new SimilarityLookupRequest ();
-            request.WithResponseGroup ("Large");
+            // Request, ItemIds, Small, Medium, Large, Offers, OfferFull, OfferSummary, OfferListings, PromotionSummary, 
+            // PromotionDetails, Variations, VariationMinimum, VariationSummary, ItemAttributes, Tracks, Accessories, EditorialReview, 
+            // SalesRank, BrowseNodes, Images, Similarities, Reviews, Subjects, ListmaniaLists
+            request.WithResponseGroup ("Images", "ItemAttributes", "OfferSummary", "Tracks", "Reviews");
             request.WithItemId (item_id);
 
+            // maybe useful if have multiple item_ids
+            //request.WithSimilarityType ("intersection");
+
             var response = service.SimilarityLookup (request);
-            Console.WriteLine (response.ToXML ());
+
+            /*private class AmazonAlbum
+            {
+                string Title;
+                string Artist;
+                string Label;
+                string Genre;
+                DateTime ReleaseDate;
+
+                string ASIN;
+                string Url;
+                double Rating;
+                int Ratings;
+                string Price;
+            }
+
+            private class AmazonTrack
+            {
+            }*/
+
+            //foreach (var itemz in response.Items) {
+              //  var item = itemz.Item.Item;
+                //var attr = item.ItemAttributes;
+                //Console.WriteLine ("asin: {0}, attr.binding: {1}", item.ASIN, attr.Binding);
+
+                
+                //attr.ProductTypeName; //DOWNLOADABLE_MUSIC_ALBUM -- DOWNLOADABLE_MUSIC_TRACK
+                //attr.Creator list
+                /*attr.Genre;
+                attr.Label;
+                attr.ReleaseDate;
+                attr.Title;
+
+                item.OfferSummary.LowestNewPrice;
+                item.CustomerReviews.AverageRating;
+                item.CustomerReviews.TotalReviews;
+                item.ASIN;
+                item.Tracks
+
+                //item.EditorialReviews.Source == "Product Description", "Album Description"
+                
+                    
+                //item.Item.Item.ItemAttributes.Genre
+                //item.Item.Item.ItemAttributes.Label
+                //item.Item.Item.ItemAttributes.ListPrice
+                //item.Item.Item.ItemAttributes.MediaType
+                */
+            //}
+            
+
+            System.IO.File.WriteAllText ("amazon-similar.xml", response.ToXML ());
         }
 
         public void Initialize ()
         {
             //TestLookup ();
-            FindSimilar ("B0012EJVIA");
+            //FindSimilar ("B0012EJVIA");
+            //FindItems ();
         }
 
         public void TestLookup ()
diff --git a/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonUtils.cs b/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonUtils.cs
new file mode 100644
index 0000000..4f0ffa3
--- /dev/null
+++ b/src/Extensions/Banshee.Amazon/Banshee.Amazon/AmazonUtils.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Amazon.ECS;
+using Amazon.ECS.Query;
+using Amazon.ECS.Mock;
+using Amazon.ECS.Model;
+
+namespace Banshee.Amazon
+{
+    public static class AmazonUtils
+    {
+        private const string ACCESS_KEY = "1WX2TV6EWH519QW2V482";
+        private const string AFFILIATE_TAG = "banshee";
+        private const string PREVIEW_URL_FMT = "http://www.amazon.com/gp/dmusic/media/sample.m3u/ref=dm_sp_smpl?ie=UTF8&catalogItemType=track&ASIN={0}";;
+
+        private const string MP3_ALBUMS_NODE = "324381011";
+        private const string MP3_SONGS_NODE =  "324382011";
+
+        private const string MP3_ALBUMS_FREE_NODE = "318774011";
+        private const string MP3_SONG_FREE_NODE = "334897011";
+
+        private static AmazonECSQuery service = new AmazonECSQuery (ACCESS_KEY, AFFILIATE_TAG);
+
+        public static string PreviewPlaylistUrl (string asin)
+        {
+            return String.Format (PREVIEW_URL_FMT, asin);
+        }
+
+        public static IEnumerable<Item> FindItems (string artist, bool mp3, bool returnTracks)
+        {
+            ItemSearchRequest request = new ItemSearchRequest ();
+
+            if (mp3) {
+                request.WithSearchIndex ("MP3Downloads");
+                request.WithBrowseNode (returnTracks ? MP3_SONGS_NODE : MP3_ALBUMS_NODE);
+                request.Author = artist;
+            } else {
+                request.WithSearchIndex ("Music");
+                request.Artist = artist;
+            };
+
+            // TODO the API now supports RelationshipType = Tracks, RelatedItems response group
+            // but the C# API is out of date.
+
+            request.WithSort ("salesrank");
+            //request.WithSort ("relevancerank");
+            request.WithResponseGroup ("Large", "VariationOffers", "Offers", "ItemAttributes", "Tags", "Images", "Reviews", "AlternateVersions", "Tracks", "Variations", "Similarities");
+
+            try {
+                ItemSearchResponse response = service.ItemSearch (request);
+                System.IO.File.WriteAllText (String.Format ("amazon-{0}-search.xml", artist), response.ToXML ());
+                return response.Items[0].Item;
+            } catch (AmazonECSException e) {
+                Hyena.Log.Exception (e);
+                return Enumerable.Empty<Item> ();
+            }
+        }
+
+        // "http://www.amazon.com/gp/dmusic/order/handle-buy-box.html/ref=dm_dp_buy?ie=UTF8&isTrack=0&asin.0=B0012EJVIA&initial=1&tryInPlace=0&session-id=182-9490740-6651605";
+
+        public static Cart GetCart (string id, string hmac)
+        {
+            var request = new CartGetRequest ();
+            request.WithCartId (id);
+            request.WithHMAC (hmac);
+            request.WithResponseGroup ("Cart");
+            var response = service.CartGet (request);
+
+            return response.Cart[0];
+        }
+
+        public static Cart CreateCart (params string [] items)
+        {
+            var request = new CartCreateRequest ();
+            if (items != null) {
+                request.WithItems (new CartCreateItems ().WithItem (
+                    items.Select<string, CartCreateItem> (NewCartCreateItem).ToArray ()
+                ));
+            }
+
+            // Request, Cart, CartSimilarities, CartTopSellers, CartNewReleases
+            request.WithResponseGroup ("Cart");
+            request.WithMergeCart ("True");
+
+            var response = service.CartCreate (request);
+            Console.WriteLine ("AddToCart, have {0} carts..", response.Cart.Count);
+            return response.Cart[0];
+        }
+
+        public static void AddToCart (Cart cart, params string [] items)
+        {
+            var request = new CartAddRequest ();
+
+            request.WithItems (new CartAddItems ().WithItem (
+                items.Select<string, CartAddItem> (NewCartAddItem).ToArray ()
+            ));
+            request.WithCartId (cart.CartId);
+            request.WithHMAC (cart.HMAC);
+            request.WithResponseGroup ("Cart");
+            request.WithMergeCart ("True");
+            var response = service.CartAdd (request);
+            Console.WriteLine ("AddToCart, have {0} carts..", response.Cart.Count);
+        }
+
+        private static CartCreateItem NewCartCreateItem (string asin)
+        {
+            return new CartCreateItem () {
+                Quantity = 1,
+                ASIN = asin,
+                AssociateTag = AFFILIATE_TAG
+            };
+        }
+
+        private static CartAddItem NewCartAddItem (string asin)
+        {
+            return new CartAddItem () {
+                Quantity = 1,
+                ASIN = asin,
+                AssociateTag = AFFILIATE_TAG
+            };
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.Amazon/Makefile.am b/src/Extensions/Banshee.Amazon/Makefile.am
index 7a19fcb..063b268 100644
--- a/src/Extensions/Banshee.Amazon/Makefile.am
+++ b/src/Extensions/Banshee.Amazon/Makefile.am
@@ -4,9 +4,15 @@ LINK = $(REF_EXTENSION_AMAZON)
 INSTALL_DIR = $(EXTENSIONS_INSTALL_DIR)
 
 SOURCES =  \
-	Banshee.Amazon/AmazonTest.cs
+	Banshee.Amazon/AmazonActions.cs \
+	Banshee.Amazon/AmazonPane.cs \
+	Banshee.Amazon/AmazonPreviewTrackInfo.cs \
+	Banshee.Amazon/AmazonTest.cs \
+	Banshee.Amazon/AmazonUtils.cs
 
-RESOURCES = Banshee.Amazon.addin.xml
+RESOURCES =  \
+	Banshee.Amazon.addin.xml \
+	Resources/GlobalUI.xml
 
 include $(top_srcdir)/build/build.mk
 
diff --git a/src/Extensions/Banshee.Amazon/Resources/GlobalUI.xml b/src/Extensions/Banshee.Amazon/Resources/GlobalUI.xml
new file mode 100644
index 0000000..245dac1
--- /dev/null
+++ b/src/Extensions/Banshee.Amazon/Resources/GlobalUI.xml
@@ -0,0 +1,7 @@
+<ui>
+    <toolbar name="HeaderToolbar">
+        <placeholder name="SourceActions">
+            <toolitem name="AmazonDetails" action="AmazonDetailsAction"/>
+        </placeholder>
+    </toolbar>
+</ui>
diff --git a/src/Extensions/Banshee.Amazon/ThemeIcons/16x16/categories/amazon.png b/src/Extensions/Banshee.Amazon/ThemeIcons/16x16/categories/amazon.png
new file mode 100644
index 0000000..31246ea
Binary files /dev/null and b/src/Extensions/Banshee.Amazon/ThemeIcons/16x16/categories/amazon.png differ
diff --git a/src/Extensions/Banshee.Amazon/ThemeIcons/22x22/categories/amazon.png b/src/Extensions/Banshee.Amazon/ThemeIcons/22x22/categories/amazon.png
new file mode 100644
index 0000000..ba0add0
Binary files /dev/null and b/src/Extensions/Banshee.Amazon/ThemeIcons/22x22/categories/amazon.png differ
diff --git a/src/Extensions/Banshee.Amazon/ThemeIcons/24x24/categories/amazon.png b/src/Extensions/Banshee.Amazon/ThemeIcons/24x24/categories/amazon.png
new file mode 100644
index 0000000..daa9876
Binary files /dev/null and b/src/Extensions/Banshee.Amazon/ThemeIcons/24x24/categories/amazon.png differ
diff --git a/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs b/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs
index a2c6786..3060521 100644
--- a/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs
+++ b/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Radio/LastfmSourceContents.cs
@@ -11,6 +11,7 @@ using Banshee.ServiceStack;
 using Banshee.Collection;
 using Banshee.Collection.Gui;
 using Banshee.Gui;
+using Banshee.Gui.Widgets;
 using Banshee.Sources.Gui;
 using Banshee.Web;
 
@@ -267,36 +268,5 @@ namespace Banshee.Lastfm.Radio
         }
     }
 
-    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));
-            };
-        }
-    }
 }
diff --git a/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationPane.cs b/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationPane.cs
index 20356bf..5d331a8 100644
--- a/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationPane.cs
+++ b/src/Extensions/Banshee.Lastfm/Banshee.Lastfm.Recommendations/RecommendationPane.cs
@@ -51,6 +51,7 @@ using Banshee.Base;
 using Banshee.Configuration;
 using Banshee.ServiceStack;
 using Banshee.Gui;
+using Banshee.Gui.Widgets;
 using Banshee.Networking;
 
 using Banshee.Collection;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]