[banshee: 11/61] [InternetArchive] Beginnings of a new item source



commit 1252066951bda238ce5e2d2015804a40f1fc55e5
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Wed Oct 7 23:04:38 2009 -0700

    [InternetArchive] Beginnings of a new item source
    
    Each search result from archive.org shown in the main IA source can
    contain many actual media files.  This commit adds the beginning of a
    new source (and special content/view) for viewing those files, viewing
    the full description and reviews for the item, and eventually
    downloading the files.

 .../Banshee.InternetArchive/File.cs                |  113 ++++++++++
 .../Banshee.InternetArchive/Item.cs                |  134 ++++++++++++
 .../Banshee.InternetArchive/ItemSource.cs          |  174 ++++++++++++++++
 .../Banshee.InternetArchive/ItemSourceContents.cs  |  219 ++++++++++++++++++++
 .../Banshee.InternetArchive/Source.cs              |    9 +-
 .../InternetArchive/Item.cs                        |   36 +++-
 .../InternetArchive/JsonItem.cs                    |   38 +++-
 .../InternetArchive/Search.cs                      |   20 --
 src/Extensions/Banshee.InternetArchive/Makefile.am |    4 +
 9 files changed, 715 insertions(+), 32 deletions(-)
---
diff --git a/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/File.cs b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/File.cs
new file mode 100644
index 0000000..1b99dc7
--- /dev/null
+++ b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/File.cs
@@ -0,0 +1,113 @@
+//
+// File.cs
+//
+// Authors:
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2009 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 System.Linq;
+
+using Mono.Unix;
+
+using Hyena.Json;
+
+using InternetArchive;
+using IA=InternetArchive;
+
+namespace Banshee.InternetArchive
+{
+    public class File
+    {
+        JsonObject file;
+
+        public File (JsonObject file)
+        {
+            this.file = file;
+        }
+
+        private long GetLong (string i)
+        {
+            return i == null ? 0 : Int64.Parse (i);
+        }
+
+        private int GetInt (string i)
+        {
+            return i == null ? 0 : Int32.Parse (i);
+        }
+
+        private TimeSpan GetTimeSpan (string i)
+        {
+            if (i == null)
+                return TimeSpan.Zero;
+
+            int h = 0, m = 0, s = 0;
+            var bits = i.Split (':');
+
+            if (bits.Length > 0)
+                s = Int32.Parse (bits[bits.Length - 1]);
+
+            if (bits.Length > 1)
+                m = Int32.Parse (bits[bits.Length - 2]);
+
+            if (bits.Length > 2)
+                h = Int32.Parse (bits[bits.Length - 3]);
+
+            return new TimeSpan (h, m, s);
+        }
+
+        public string Location {
+            get { return file.Get<string> ("location"); }
+        }
+
+        public long Size {
+            get { return GetLong (file.Get<string> ("size")); }
+        }
+
+        public int Track {
+            get { return GetInt (file.Get<string> ("track")); }
+        }
+
+        public string Creator {
+            get { return file.Get<string> ("creator"); }
+        }
+
+        public string Title {
+            get { return file.Get<string> ("title"); }
+        }
+
+        public int BitRate {
+            get { return GetInt (file.Get<string> ("bitrate")); }
+        }
+
+        public string Format {
+            get { return file.Get<string> ("format"); }
+        }
+
+        public TimeSpan Length {
+            get { return GetTimeSpan (file.Get<string> ("length")); }
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/Item.cs b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/Item.cs
new file mode 100644
index 0000000..63c11b7
--- /dev/null
+++ b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/Item.cs
@@ -0,0 +1,134 @@
+//
+// Item.cs
+//
+// Authors:
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2009 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 System.Linq;
+
+using Mono.Unix;
+
+using Hyena.Json;
+
+using InternetArchive;
+using IA=InternetArchive;
+
+namespace Banshee.InternetArchive
+{
+    public class Item
+    {
+        JsonObject details;
+        JsonObject metadata;
+
+        public static Item LoadOrCreate (string id)
+        {
+            /*var item = Provider.LoadFromId (id);
+            if (item != null)
+                return item;*/
+
+            return new Item (id);
+        }
+
+        private Item (string id)
+        {
+            Id = id;
+            //Provider.Save ();
+            LoadDetails ();
+        }
+
+        //[DatabaseColumn (PrimaryKey=true)]
+        public long DbId { get; set; }
+
+        //[DatabaseColumn]
+        public string Id { get; set; }
+
+        //[DatabaseColumn]
+        public string JsonDetails { get; set; }
+
+        //[DatabaseColumn]
+        public bool IsHidden { get; set; }
+
+        public string Title {
+            get { return metadata.GetJoined ("title", System.Environment.NewLine); }
+        }
+
+        public string Description {
+            get { return metadata.GetJoined ("description", System.Environment.NewLine); }
+        }
+
+        public string Creator {
+            get { return metadata.Get<string> ("creator"); }
+        }
+
+        public DateTime DateCreated {
+            get { return DateTime.Parse (metadata.Get<string> ("date")); }
+        }
+
+        public IEnumerable<File> Files {
+            get {
+                var files = details["files"] as JsonObject;
+                foreach (JsonObject file in files.Values) {
+                    yield return new File (file);
+                }
+            }
+        }
+
+        private bool LoadDetails ()
+        {
+            // First see if we already have the Hyena.JsonObject parsed
+            if (details != null) {
+                return true;
+            }
+
+            // If not, see if we have a copy in the database, and parse that
+            /*if (JsonDetails != null) {
+                details = new Hyena.Json.Deserializer (JsonDetails).Deserialize () as JsonObject;
+                return true;
+            }*/
+
+
+            details = new Hyena.Json.Deserializer (System.IO.File.ReadAllText ("item.json")).Deserialize () as JsonObject;
+            metadata = details["metadata"] as JsonObject;
+            return details != null;
+            
+            // We don't; grab it from archive.org and parse it
+            /*string json_str = new IA.Item () { Id = Id }.GetDetails ();
+
+            if (json_str != null) {
+                details = new Hyena.Json.Deserializer (json_str).Deserialize () as JsonObject;
+
+                if (details != null) {
+                    JsonDetails = json_str;
+                    Save ();
+                    return true;
+                }
+            }*/
+
+            //return false;
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/ItemSource.cs b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/ItemSource.cs
new file mode 100644
index 0000000..8b067ee
--- /dev/null
+++ b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/ItemSource.cs
@@ -0,0 +1,174 @@
+//
+// ItemSource.cs
+//
+// Authors:
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2009 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 System.Linq;
+
+using Mono.Unix;
+
+using Hyena.Collections;
+using Hyena.Data.Sqlite;
+
+using Banshee.Base;
+using Banshee.Collection;
+using Banshee.Collection.Database;
+using Banshee.Configuration;
+using Banshee.Database;
+using Banshee.Gui;
+using Banshee.Library;
+using Banshee.MediaEngine;
+using Banshee.PlaybackController;
+using Banshee.Playlist;
+using Banshee.Preferences;
+using Banshee.ServiceStack;
+using Banshee.Sources;
+
+using IA=InternetArchive;
+
+namespace Banshee.InternetArchive
+{
+    public class ItemSource : Banshee.Sources.PrimarySource
+    {
+        //private Actions actions;
+        //private Gtk.Widget header_widget;
+        //private IA.Search search;
+        private string status_text = "";
+        private Item item;
+
+        public ItemSource (string name, string id) : base (name, name, "internet-archive-" + id, 210)
+        {
+            item = Item.LoadOrCreate (id);
+
+            IsLocal = false;
+            SupportsPlaylists = false;
+            //Properties.SetStringList ("Icon.Name", "video-x-generic", "video", "source-library");
+
+            //Properties.SetString ("ActiveSourceUIResource", "ItemActiveSourceUI.xml");
+            //Properties.Set<bool> ("ActiveSourceUIResourcePropagate", true);
+
+            //actions = new Actions (this);
+            //
+            Properties.Set<Gtk.Widget> ("Nereid.SourceContents", new ItemSourceContents (item));
+
+            AfterInitialized ();
+
+            DatabaseTrackModel.CanReorder = false;
+
+            if (item == null)
+                Console.WriteLine ("foo");
+
+            /*if (header_widget == null) {
+                header_widget = new HeaderFilters (this);
+                header_widget.ShowAll ();
+                Properties.Set<Gtk.Widget> ("Nereid.SourceContents.HeaderWidget", header_widget);
+            }*/
+        }
+
+        public override void Reload ()
+        {
+            ThreadAssist.SpawnFromMain (ThreadedReload);
+        }
+
+        private void ThreadedReload ()
+        {
+        }
+
+        public override int Count {
+            get { return 0; }
+        }
+
+        protected override int StatusFormatsCount { get { return 1; } }
+
+        public override string GetStatusText ()
+        {
+            return status_text;
+        }
+
+        /*public override bool AcceptsInputFromSource (Source source)
+        {
+            return false;
+        }*/
+
+        // DatabaseSource overrides
+
+        public override bool ShowBrowser { 
+            get { return false; }
+        }
+
+        public override bool CanShuffle {
+            get { return false; }
+        }
+
+        public override bool CanAddTracks {
+            get { return false; }
+        }
+
+        public override bool CanRemoveTracks {
+            get { return false; }
+        }
+
+        public override bool CanDeleteTracks {
+            get { return false; }
+        }
+
+        protected override bool HasArtistAlbum {
+            get { return false; }
+        }
+
+        public override bool HasEditableTrackProperties {
+            get { return false; }
+        }
+
+        public override bool HasViewableTrackProperties {
+            get { return false; }
+        }
+
+        public override bool CanSearch {
+            get { return false; }
+        }
+
+        protected override void Initialize ()
+        {
+            base.Initialize ();
+
+            //InstallPreferences ();
+        }
+
+        public override void Dispose ()
+        {
+            /*if (actions != null) {
+                actions.Dispose ();
+            }*/
+
+            base.Dispose ();
+
+            //UninstallPreferences ();
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/ItemSourceContents.cs b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/ItemSourceContents.cs
new file mode 100644
index 0000000..03e1dfd
--- /dev/null
+++ b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/ItemSourceContents.cs
@@ -0,0 +1,219 @@
+//
+// ItemSourceContents.cs
+//
+// Authors:
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2009 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 System.Linq;
+
+using Mono.Unix;
+using Gtk;
+
+using Hyena.Collections;
+using Hyena.Data.Sqlite;
+
+using Hyena.Data;
+using Hyena.Data.Gui;
+
+using Banshee.Base;
+using Banshee.Collection;
+using Banshee.Collection.Gui;
+using Banshee.Collection.Database;
+using Banshee.Configuration;
+using Banshee.Database;
+using Banshee.Gui;
+using Banshee.Library;
+using Banshee.MediaEngine;
+using Banshee.PlaybackController;
+using Banshee.Playlist;
+using Banshee.Preferences;
+using Banshee.ServiceStack;
+using Banshee.Sources;
+
+using IA=InternetArchive;
+
+namespace Banshee.InternetArchive
+{
+    public class ItemSourceContents : Gtk.HBox, Banshee.Sources.Gui.ISourceContents
+    {
+        private ItemSource source;
+        Item item;
+
+        public ItemSourceContents (Item item)
+        {
+            this.item = item;
+
+            Spacing = 6;
+
+            BuildInfoBox ();
+            BuildFilesBox ();
+
+            ShowAll ();
+        }
+
+#region ISourceContents
+
+        public bool SetSource (ISource source)
+        {
+            this.source = source as ItemSource;
+            return this.source != null;
+        }
+
+        public void ResetSource ()
+        {
+        }
+
+        public ISource Source { get { return source; } }
+
+        public Widget Widget { get { return this; } }
+
+#endregion
+
+        private void BuildInfoBox ()
+        {
+            var frame = new Hyena.Widgets.RoundedFrame ();
+            var vbox = new VBox ();
+            vbox.Spacing = 6;
+
+            // Title
+            var title = new Label () {
+                Markup = String.Format ("<big><b>{0}</b></big>", GLib.Markup.EscapeText (item.Title))
+            };
+
+            // Description
+            var desc = new Hyena.Widgets.WrapLabel () {
+                Markup = item.Description
+            };
+
+            var desc_sw = new Gtk.ScrolledWindow ();
+            desc_sw.AddWithViewport (desc);
+
+            // Reviews
+            var reviews = new Label () {
+                Markup = String.Format ("<big><b>{0}</b></big>", GLib.Markup.EscapeText (Catalog.GetString ("Reviews")))
+            };
+
+            vbox.PackStart (title,   false, false, 0);
+            vbox.PackStart (desc_sw, true,  true,  0);
+            vbox.PackStart (reviews, false, false, 0);
+            frame.Child = vbox;
+
+            PackStart (frame, true, true, 0);
+        }
+
+        private void BuildFilesBox ()
+        {
+            var vbox = new VBox ();
+            vbox.Spacing = 6;
+
+            var format_list = new Hyena.Data.Gui.ListView<string> () {
+                HeaderVisible = false
+            };
+            var format_sw = new Gtk.ScrolledWindow ();
+            format_sw.Child = format_list;
+            var format_cols = new ColumnController ();
+            format_cols.Add (new Column ("format", new ColumnCellText (null, true), 1.0));
+            format_list.ColumnController = format_cols;
+
+            var file_list = new ListView<TrackInfo> () {
+                HeaderVisible = false
+            };
+
+            var files_model = new MemoryTrackListModel ();
+            var columns = new DefaultColumnController ();
+            var file_columns = new ColumnController ();
+            file_columns.AddRange (
+                columns.IndicatorColumn,
+                columns.TrackColumn,
+                columns.TitleColumn,
+                columns.DurationColumn,
+                columns.FileSizeColumn
+            );
+
+            foreach (var col in file_columns) {
+                col.Visible = true;
+            }
+
+            file_list.ColumnController = file_columns;
+
+            var file_sw = new Gtk.ScrolledWindow ();
+            file_sw.Child = file_list;
+
+            var format_model = new MemoryListModel<string> ();
+            var files = new List<TrackInfo> ();
+
+            foreach (var f in item.Files) {
+                var track = new TrackInfo () {
+                    Uri         = new SafeUri (f.Location),
+                    FileSize    = f.Size,
+                    TrackNumber = f.Track,
+                    ArtistName  = f.Creator,
+                    TrackTitle  = f.Title,
+                    BitRate     = f.BitRate,
+                    MimeType    = f.Format,
+                    Duration    = f.Length
+                };
+
+                files.Add (track);
+
+                if (format_model.IndexOf (f.Format) == -1) {
+                    format_model.Add (f.Format);
+                }
+            }
+
+            // HACK to fix up the times; sometimes the VBR MP3 file will have it but Ogg won't
+            foreach (var a in files) {
+                foreach (var b in files) {
+                    if (a.TrackTitle == b.TrackTitle) {
+                        a.Duration = b.Duration = a.Duration > b.Duration ? a.Duration : b.Duration;
+                    }
+                }
+            }
+
+            file_list.SetModel (files_model);
+            format_list.SetModel (format_model);
+
+            format_list.SelectionProxy.Changed += (o, a) => {
+                files_model.Clear ();
+
+                var selected_formats = new ModelSelection<string> (format_model, format_list.Selection);
+                foreach (var track in files) {
+                    if (selected_formats.Contains (track.MimeType)) {
+                        files_model.Add (track);
+                    }
+                }
+
+                files_model.Reload ();
+            };
+
+            vbox.PackStart (format_sw, false, false, 0);
+            vbox.PackStart (file_sw,   true,  true,  0);
+
+            PackStart (vbox, true, true, 0);
+        }
+    }
+}
diff --git a/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/Source.cs b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/Source.cs
index 17946cb..f7740b7 100644
--- a/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/Source.cs
+++ b/src/Extensions/Banshee.InternetArchive/Banshee.InternetArchive/Source.cs
@@ -64,7 +64,7 @@ namespace Banshee.InternetArchive
 
         public IA.Search Search { get { return search; } }
 
-        public Source () : base (name, name, "internet-archive", 210)
+        public Source () : base (name, name, "internet-archive", 190)
         {
             IA.Search.UserAgent = Banshee.Web.Browser.UserAgent;
             IA.Search.TimeoutMs = 12*1000;
@@ -131,6 +131,9 @@ namespace Banshee.InternetArchive
                 header_widget.ShowAll ();
                 Properties.Set<Gtk.Widget> ("Nereid.SourceContents.HeaderWidget", header_widget);
             }
+
+            var src = new ItemSource ("Fake Name", "foo");
+            AddChildSource (src);
         }
 
         public override void Reload ()
@@ -264,6 +267,10 @@ namespace Banshee.InternetArchive
             get { return false; }
         }
 
+        public override bool HasViewableTrackProperties {
+            get { return false; }
+        }
+
         public override bool CanSearch {
             get { return false; }
         }
diff --git a/src/Extensions/Banshee.InternetArchive/InternetArchive/Item.cs b/src/Extensions/Banshee.InternetArchive/InternetArchive/Item.cs
index 8167b27..ee5e4e5 100644
--- a/src/Extensions/Banshee.InternetArchive/InternetArchive/Item.cs
+++ b/src/Extensions/Banshee.InternetArchive/InternetArchive/Item.cs
@@ -52,7 +52,7 @@ namespace InternetArchive
             get { return Get<string> (Field.Identifier); }
         }
 
-        public string JsonDetailsUrl {
+        private string JsonDetailsUrl {
             get { return String.Format ("{0}&output=json", WebpageUrl); }
         }
 
@@ -60,6 +60,40 @@ namespace InternetArchive
             get { return String.Format ("http://www.archive.org/details/{0}";, Id); }
         }
 
+        public string GetDetails ()
+        {
+            HttpWebResponse response = null;
+            string url = null;
+
+            try {
+                url = JsonDetailsUrl;
+                Hyena.Log.Debug ("ArchiveSharp Getting Details", url);
+
+                var request = (HttpWebRequest) WebRequest.Create (url);
+                request.UserAgent = Search.UserAgent;
+                request.Timeout   = Search.TimeoutMs;
+                request.KeepAlive = Search.KeepAlive;
+
+                response = (HttpWebResponse) request.GetResponse ();
+                using (Stream stream = response.GetResponseStream ()) {
+                    using (StreamReader reader = new StreamReader (stream)) {
+                        return reader.ReadToEnd ();
+                    }
+                }
+            } catch (Exception e) {
+                Hyena.Log.Exception (String.Format ("Error searching {0}", url), e);
+                return null;
+            } finally {
+                if (response != null) {
+                    if (response.StatusCode != HttpStatusCode.OK) {
+                        Hyena.Log.WarningFormat ("Got status {0} searching {1}", response.StatusCode, url);
+                    }
+                    response.Close ();
+                    response = null;
+                }
+            }
+        }
+
         public abstract T Get<T> (Field field);
     }
 }
diff --git a/src/Extensions/Banshee.InternetArchive/InternetArchive/JsonItem.cs b/src/Extensions/Banshee.InternetArchive/InternetArchive/JsonItem.cs
index 0d09495..b908305 100644
--- a/src/Extensions/Banshee.InternetArchive/InternetArchive/JsonItem.cs
+++ b/src/Extensions/Banshee.InternetArchive/InternetArchive/JsonItem.cs
@@ -34,6 +34,33 @@ using Hyena.Json;
 
 namespace InternetArchive
 {
+    public static class JsonExtensions
+    {
+        public static T Get<T> (this JsonObject item, string key)
+        {
+            object result;
+            if (item.TryGetValue (key, out result)) {
+                try {
+                    return (T)result;
+                } catch {
+                    Console.WriteLine ("Couldn't cast {0} ({1}) as {2} for key {3}", result, result.GetType (), typeof(T), key);
+                }
+            }
+
+            return default (T);
+        }
+
+        public static string GetJoined (this JsonObject item, string key, string with)
+        {
+            var ary = item.Get<System.Collections.IEnumerable> (key);
+            if (ary != null) {
+                return String.Join (with, ary.Cast<object> ().Select (o => o.ToString ()).ToArray ());
+            }
+
+            return null;
+        }
+    }
+
     public class JsonItem : Item
     {
         JsonObject item;
@@ -45,16 +72,7 @@ namespace InternetArchive
 
         public override T Get<T> (Field field)
         {
-            object result;
-            if (item.TryGetValue (field.Id, out result)) {
-                try {
-                return (T)result;
-                } catch {
-                    Console.WriteLine ("Couldn't cast {0} ({1}) as {2}", result, result.GetType (), typeof(T));
-                }
-            }
-
-            return default (T);
+            return item.Get<T> (field.Id);
         }
     }
 }
diff --git a/src/Extensions/Banshee.InternetArchive/InternetArchive/Search.cs b/src/Extensions/Banshee.InternetArchive/InternetArchive/Search.cs
index 2f5f4d6..8c41db1 100644
--- a/src/Extensions/Banshee.InternetArchive/InternetArchive/Search.cs
+++ b/src/Extensions/Banshee.InternetArchive/InternetArchive/Search.cs
@@ -32,26 +32,6 @@ using System.Collections.Generic;
 
 namespace InternetArchive
 {
-    public static class Test
-    {
-        public static void Main ()
-        {
-            Hyena.Log.Debugging = true;
-            var resp = new Search ().GetResults ();
-            Console.WriteLine ("response:\n{0}", resp);
-
-            var json = new Hyena.Json.Deserializer (resp);
-            Console.WriteLine ("json:\n");
-            (json.Deserialize () as Hyena.Json.JsonObject).Dump ();
-
-            /*title subject description 
-            creator 
-            downloads
-            num_reviews
-            licenseurl*/
-        }
-    }
-
     public class Search
     {
         List<Sort> sorts = new List<Sort> ();
diff --git a/src/Extensions/Banshee.InternetArchive/Makefile.am b/src/Extensions/Banshee.InternetArchive/Makefile.am
index 64590df..6011294 100644
--- a/src/Extensions/Banshee.InternetArchive/Makefile.am
+++ b/src/Extensions/Banshee.InternetArchive/Makefile.am
@@ -16,6 +16,10 @@ SOURCES = \
 	InternetArchive/JsonItem.cs \
 	InternetArchive/Sort.cs \
 	Banshee.InternetArchive/Actions.cs \
+	Banshee.InternetArchive/File.cs \
+	Banshee.InternetArchive/Item.cs \
+	Banshee.InternetArchive/ItemSource.cs \
+	Banshee.InternetArchive/ItemSourceContents.cs \
 	Banshee.InternetArchive/HeaderFilters.cs \
 	Banshee.InternetArchive/Source.cs
 



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