banshee r4194 - in trunk/banshee: . src/Extensions/Banshee.Daap src/Extensions/Banshee.Daap/Banshee.Daap src/Extensions/Banshee.Daap/Daap src/Extensions/Banshee.Daap/Resources



Author: gburt
Date: Tue Jun 24 19:00:45 2008
New Revision: 4194
URL: http://svn.gnome.org/viewvc/banshee?rev=4194&view=rev

Log:
2008-06-24  Gabriel Burt  <gabriel burt gmail com>

	* src/Extensions/Banshee.Daap/Daap/Database.cs: Style.

	* src/Extensions/Banshee.Daap/Resources/Banshee.Daap.addin.xml:
	* src/Extensions/Banshee.Daap/Banshee.Daap.addin.xml: Move up from
	Resources, and add original DAAP plugin authors.

	* src/Extensions/Banshee.Daap/Banshee.Daap/DaapProxyWebServer.cs: Copied
	from stable branch.

	* src/Extensions/Banshee.Daap/Banshee.Daap/DaapService.cs: Create a new
	proxy server instance.  Make new shares pulsate.  Dispose shares
	recursively.

	* src/Extensions/Banshee.Daap/Banshee.Daap/DaapSource.cs: Prevent creating
	playlists/smart playlists, initialize count to 0, [un]register our
	database with the proxy server.

	* src/Extensions/Banshee.Daap/Banshee.Daap/DaapTrackInfo.cs: Use the proxy
	server url, don't set CanSavetoDatabase to false, that prevents daap
	tracks from being used with the queue.

	* src/Extensions/Banshee.Daap/Banshee.Daap/DaapPlaylistSource.cs: Override
	quite a few things: no removing/deleting tracks, renaming, unmapping, or
	adding tracks.

	* src/Extensions/Banshee.Daap/Banshee.Daap/DaapContainerSource.cs:
	CanRename = false.

	* src/Extensions/Banshee.Daap/Banshee.Daap/DaapErrorView.cs: Copied from
	stable, not yet used.

	* src/Extensions/Banshee.Daap/Makefile.am: Add the proxy server class,
	move the addins file.


Added:
   trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap.addin.xml   (contents, props changed)
      - copied, changed from r4191, /trunk/banshee/src/Extensions/Banshee.Daap/Resources/Banshee.Daap.addin.xml
   trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapErrorView.cs
   trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapProxyWebServer.cs
Removed:
   trunk/banshee/src/Extensions/Banshee.Daap/Resources/Banshee.Daap.addin.xml
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapContainerSource.cs
   trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapPlaylistSource.cs
   trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapService.cs
   trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapSource.cs
   trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapTrackInfo.cs
   trunk/banshee/src/Extensions/Banshee.Daap/Daap/Database.cs
   trunk/banshee/src/Extensions/Banshee.Daap/Makefile.am

Copied: trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap.addin.xml (from r4191, /trunk/banshee/src/Extensions/Banshee.Daap/Resources/Banshee.Daap.addin.xml)
==============================================================================
--- /trunk/banshee/src/Extensions/Banshee.Daap/Resources/Banshee.Daap.addin.xml	(original)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap.addin.xml	Tue Jun 24 19:00:45 2008
@@ -6,8 +6,8 @@
     copyright="Â 2008 Alexander Hixon. Licensed under the MIT X11 license."
     name="DAAP"
     category=""
-    description=""
-    author="Alexander Hixon"
+    description="Browse and listen to music shared over your local network."
+    author="Aaron Bockover, James Willcox, Alexander Hixon, Gabriel Burt"
     url="http://banshee-project.org/";
     defaultEnabled="true">
 

Modified: trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapContainerSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapContainerSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapContainerSource.cs	Tue Jun 24 19:00:45 2008
@@ -51,6 +51,10 @@
             get { return false; }
         }
         
+        public override bool CanRename {
+            get { return false; }
+        }
+        
         protected override string TypeUniqueId {
             get { return "daap-container"; }
         }

Added: trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapErrorView.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapErrorView.cs	Tue Jun 24 19:00:45 2008
@@ -0,0 +1,143 @@
+/***************************************************************************
+ *  DaapErrorView.cs
+ *
+ *  Copyright (C) 2006 Novell, Inc.
+ *  Written by Aaron Bockover <aaron abock org>
+ ****************************************************************************/
+
+/*  THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW: 
+ *
+ *  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 Mono.Unix;
+using Gtk;
+
+using Banshee.Base;
+using Banshee.Widgets;
+
+namespace Banshee.Plugins.Daap
+{
+    public enum DaapErrorType {
+        BrokenAuthentication,
+        InvalidAuthentication,
+        UserDisconnect
+    }
+    
+    public class DaapErrorView : ShadowContainer
+    {
+        private MessagePane pane;
+        private bool info_link_clicked;
+        private DaapSource source;
+        private DaapErrorType failure;
+        
+        public DaapErrorView(DaapSource source, DaapErrorType failure) : base()
+        {
+            AppPaintable = true;
+            BorderWidth = 10;
+            
+            this.source = source;
+            this.failure = failure;
+            
+            pane = new MessagePane();
+            pane.HeaderIcon = IconThemeUtils.LoadIcon(48, "face-surprise", Stock.DialogError);
+            pane.ArrowIcon = IconThemeUtils.LoadIcon(24, "go-next", Stock.GoForward);
+            pane.HeaderMarkup = String.Format("<big><b>{0}</b></big>", 
+                GLib.Markup.EscapeText((failure == DaapErrorType.UserDisconnect 
+                    ? Catalog.GetString("Disconnected from music share")
+                    : Catalog.GetString("Unable to connect to music share"))));
+                
+            AddPaneItems();
+            pane.Show();
+            
+            Add(pane);
+        }
+        
+        private void AddPaneItems()
+        {
+            if(info_link_clicked) {
+                LinkLabel link = new LinkLabel();
+                link.Xalign = 0.0f;
+                link.Markup = String.Format("<u>{0}</u>", GLib.Markup.EscapeText(Catalog.GetString(
+                    "Back")));
+                    
+                link.Clicked += delegate(object o, EventArgs args) {
+                    info_link_clicked = false;
+                    pane.Clear();
+                    AddPaneItems();
+                };
+                
+                link.Show();
+                pane.Append(link, Gtk.AttachOptions.Expand | Gtk.AttachOptions.Fill, 0, true, 
+                    IconThemeUtils.LoadIcon(24, "go-previous", Stock.GoBack));
+                
+                pane.Append(Catalog.GetString(
+                    "iTunes\u00ae 7 introduced new compatibility issues and currently only " +
+                    "works with other iTunes\u00ae 7 clients.\n\n" + 
+                    "No third-party clients can connect to iTunes\u00ae music shares anymore. " + 
+                    "This is an intentional limitation by Apple in iTunes\u00ae 7 and we apologize for " + 
+                    "the unfortunate inconvenience."
+                ));
+            } else {
+                if(failure != DaapErrorType.UserDisconnect) {
+                    Label header_label = new Label();
+                    header_label.Markup = String.Format("<b>{0}</b>", GLib.Markup.EscapeText(Catalog.GetString(
+                        "Common reasons for connection failures:")));
+                    header_label.Xalign = 0.0f;
+                    header_label.Show();
+                    
+                    pane.Append(header_label, Gtk.AttachOptions.Expand | Gtk.AttachOptions.Fill, 0, false);
+                    
+                    pane.Append(Catalog.GetString("The provided login credentials are invalid"));
+                    pane.Append(Catalog.GetString("The login process was canceled"));
+                    pane.Append(Catalog.GetString("Too many users are connected to this share"));
+                } else {
+                    pane.Append(Catalog.GetString("You are no longer connected to this music share"));
+                }
+                
+                if(failure == DaapErrorType.UserDisconnect || failure == DaapErrorType.InvalidAuthentication) {
+                    Button button = new Button(Catalog.GetString("Try connecting again"));
+                    button.Clicked += delegate { source.Activate(); };
+
+                    HBox bbox = new HBox();
+                    bbox.PackStart(button, false, false, 0);
+                    bbox.ShowAll();
+
+                    pane.Append(bbox, Gtk.AttachOptions.Expand | Gtk.AttachOptions.Fill, 0, false);
+                    return;
+                }
+                
+                LinkLabel link = new LinkLabel();
+                link.Xalign = 0.0f;
+                link.Markup = String.Format("<u>{0}</u>", GLib.Markup.EscapeText(Catalog.GetString(
+                    "The music share is hosted by iTunes\u00ae 7")));
+                    
+                link.Clicked += delegate(object o, EventArgs args) {
+                    info_link_clicked = true;
+                    pane.Clear();
+                    AddPaneItems();
+                };
+                
+                link.Show();
+                pane.Append(link, Gtk.AttachOptions.Expand | Gtk.AttachOptions.Fill, 0, true);
+            }
+        }
+    }
+}

Modified: trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapPlaylistSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapPlaylistSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapPlaylistSource.cs	Tue Jun 24 19:00:45 2008
@@ -55,7 +55,7 @@
             get { return parent.Database; }
         }
         
-        public DaapPlaylistSource (DAAP.Playlist playlist, int id, DaapSource parent) : base (playlist.Name, parent.DbId)
+        public DaapPlaylistSource (DAAP.Playlist playlist, DaapSource parent) : base (playlist.Name, parent.DbId)
         {
             this.parent = parent;
             Save ();
@@ -63,18 +63,31 @@
             if (playlist.Tracks.Count > 0) {
                 //IList<DAAP.Track> tracks = playlist.Tracks;
                 int [] external_ids = new int [playlist.Tracks.Count];
-                //for (int i = 0; i < tracks.Count; i++) {
                 int i = 0;
                 foreach (DAAP.Track track in playlist.Tracks) {
-                    external_ids[i] = track.Id;
-                    i++;
+                    external_ids[i++] = track == null ? -1 : track.Id;
                 }
-                HyenaSqliteCommand.LogAll = true;
+
                 ServiceManager.DbConnection.Execute (insert_track_command, DbId, parent.DbId, external_ids);
-                HyenaSqliteCommand.LogAll = false;
             }
             SavedCount = playlist.Tracks.Count;
             OnUpdated ();
         }
+        
+        public override bool CanDeleteTracks {
+            get { return false; }
+        }
+        
+        public override bool CanAddTracks {
+            get { return false; }
+        }
+        
+        public override bool CanRename {
+            get { return false; }
+        }
+        
+        public override bool CanUnmap {
+            get { return false; }
+        }
     }
 }

Added: trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapProxyWebServer.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapProxyWebServer.cs	Tue Jun 24 19:00:45 2008
@@ -0,0 +1,388 @@
+
+/***************************************************************************
+ *  DaapProxyWebServer.cs
+ *
+ *  Copyright (C) 2005-2006 Novell, Inc.
+ *  Written by Aaron Bockover <aaron aaronbock net>
+ *             James Wilcox <snorp snorp net>
+ ****************************************************************************/
+
+/*  THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW: 
+ *
+ *  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.Text;
+using System.Web;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using System.Collections;
+
+using DAAP = Daap;
+
+namespace Banshee.Daap
+{
+    internal class DaapProxyWebServer
+    {
+        private const int ChunkLength = 8192;
+
+        private ushort port;
+        private Socket server;
+        private bool running;
+        private ArrayList clients = new ArrayList();
+        private ArrayList databases = new ArrayList();
+      
+        public DaapProxyWebServer() 
+        {
+        }
+
+        public void Start() 
+        {
+            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
+            try {
+                server.Bind(new IPEndPoint(IPAddress.Any, 8089));
+            } catch (System.Net.Sockets.SocketException) {
+                server.Bind(new IPEndPoint(IPAddress.Any, 0));
+            }
+            port = (ushort)(server.LocalEndPoint as IPEndPoint).Port;
+            server.Listen(10);
+
+            running = true;
+            Thread thread = new Thread(ServerLoop);
+            thread.IsBackground = true;
+            thread.Start();
+        }
+
+        public void Stop() 
+        {
+            running = false;
+            
+            if(server != null) {
+                server.Close();
+                server = null;
+            }
+
+            foreach(Socket client in (ArrayList)clients.Clone()) {
+                client.Close();
+            }
+        }
+        
+        public void RegisterDatabase(DAAP.Database database)
+        {
+            databases.Add(database);
+        }
+        
+        public void UnregisterDatabase(DAAP.Database database)
+        {
+            databases.Remove(database);
+        }
+        
+        private void ServerLoop()
+        {
+            while(true) {
+                try {
+                    if(!running) {
+                        break;
+                    }
+                    
+                    Socket client = server.Accept();
+                    clients.Add(client);
+                    ThreadPool.QueueUserWorkItem(HandleConnection, client);
+                } catch(SocketException e) {
+                    Hyena.Log.Exception (e);
+                    break;
+                }
+            }
+        }
+        
+        private void HandleConnection(object o) 
+        {
+            Socket client = (Socket)o;
+
+            try {
+                while(HandleRequest(client));
+            } catch(IOException) {
+            } catch(Exception e) {
+                Hyena.Log.Exception (e);
+            } finally {
+                clients.Remove(client);
+                client.Close();
+            }
+        }
+        
+        private bool HandleRequest(Socket client) 
+        {
+            if(!client.Connected) {
+                return false;
+            }
+            
+            bool keep_connection = true;
+            
+            using(StreamReader reader = new StreamReader(new NetworkStream(client, false))) {
+                string request = reader.ReadLine();
+                
+                if(request == null) {
+                    return false;
+                }
+                
+                string line = null;
+                
+                do {
+                    line = reader.ReadLine();
+                    if(line.ToLower() == "connection: close") {
+                        keep_connection = false;
+                    }
+                } while(line != String.Empty && line != null);
+                
+                string [] split_request = request.Split();
+                
+                if(split_request.Length < 3) {
+                    WriteResponse(client, HttpStatusCode.BadRequest, "Bad Request");
+                    return keep_connection;
+                } else {
+                    try {
+                        HandleValidRequest(client, split_request);
+                    } catch(IOException) {
+                        keep_connection = false;
+                    } catch(Exception e) {
+                        keep_connection = false;
+                        Console.Error.WriteLine("Trouble handling request {0}: {1}", split_request[1], e);
+                    }
+                }
+            }
+
+            return keep_connection;
+        }
+
+        private void HandleValidRequest(Socket client, string [] split_request)
+        {        
+            if(split_request[1].StartsWith("/")) {
+               split_request[1] = split_request[1].Substring(1);
+            }
+
+            string [] nodes = split_request[1].Split('/');
+            string body = String.Empty;
+            HttpStatusCode code = HttpStatusCode.OK;
+
+            if(nodes.Length == 1 && nodes[0] == String.Empty) {
+               body = GetHtmlHeader("Available Databases");
+               
+               if(databases.Count == 0) {
+                   body += "<blockquote><p><em>No databases found. Connect to a " + 
+                       "share in Banshee.</em></p></blockquote>";
+               } else {
+                   body += "<ul>";
+                   foreach(DAAP.Database database in (ArrayList)databases.Clone()) {
+                       body += String.Format("<li><a href=\"/{0}\">{1} ({2} Tracks)</a></li>",
+                           database.GetHashCode(), database.Name, database.TrackCount);
+                   }
+                   body += "</ul>";
+               }
+            } else if(nodes.Length == 1 && nodes[0] != String.Empty) {
+                bool db_found = false;
+                int id = 0;
+                try {
+                    id = Convert.ToInt32(nodes[0]);
+                } catch {
+                }
+                
+                foreach(DAAP.Database database in (ArrayList)databases.Clone()) {
+                    if(database.GetHashCode() != id) {
+                        continue;
+                    }
+                    
+                    body = GetHtmlHeader("Tracks in " + database.Name);
+                    
+                    if(database.TrackCount == 0) {
+                        body += "<blockquote><p><em>No songs in this database.</em></p></blockquote>";
+                    } else {
+                        body += "<p>Showing all " + database.TrackCount + " songs:</p><ul>";
+                        foreach(DAAP.Track song in database.Tracks) {
+                            body += String.Format("<li><a href=\"/{0}/{1}\">{2} - {3}</a> ({4}:{5})</li>",
+                                database.GetHashCode(), song.Id, song.Artist, song.Title, 
+                                song.Duration.Minutes, song.Duration.Seconds.ToString("00"));
+                        }
+                        body += "</ul>";
+                    }
+                    
+                    db_found = true;
+                    break;
+                }
+                
+                if(!db_found) {
+                    code = HttpStatusCode.BadRequest;
+                    body = GetHtmlHeader("Invalid Request");
+                    body += String.Format("<p>No database with id `{0}'</p>", id);
+                }
+            } else if(nodes.Length == 2) {
+                bool db_found = false;
+                int db_id = 0;
+                int song_id = 0;
+                
+                try {
+                    db_id = Convert.ToInt32(nodes[0]);
+                    song_id = Convert.ToInt32(nodes[1]);
+                } catch {
+                }
+                
+                foreach(DAAP.Database database in (ArrayList)databases.Clone()) {
+                    if(database.GetHashCode() != db_id) {
+                        continue;
+                    }
+                    
+                    try {
+                        DAAP.Track song = database.LookupTrackById(song_id);
+                        if(song != null) {
+                            StreamTrack(client, database, song);
+                            return;
+                        }
+                    } catch (Exception e) {
+                        Hyena.Log.Exception (e);
+                    }
+                        
+                    code = HttpStatusCode.BadRequest;
+                    body = GetHtmlHeader("Invalid Request");
+                    body += String.Format("<p>No song with id `{0}'</p>", song_id);
+                    
+                    db_found = true;
+                    break;
+                }
+                
+                if(!db_found) {
+                    code = HttpStatusCode.BadRequest;
+                    body = GetHtmlHeader("Invalid Request");
+                    body += String.Format("<p>No database with id `{0}'</p>", db_id);
+                }
+            } else {
+               code = HttpStatusCode.BadRequest;
+               body = GetHtmlHeader("Invalid Request");
+               body += String.Format("<p>The request '{0}' could not be processed by server.</p>",
+                   split_request[1]);
+            }
+
+            WriteResponse(client, code, body + GetHtmlFooter());
+        }
+        
+        private void StreamTrack(Socket client, DAAP.Database database, DAAP.Track song)
+        {
+            long length;
+            Stream stream = database.StreamTrack(song, out length);
+            WriteResponseStream(client, stream, length, song.FileName);
+            stream.Close();
+            client.Close();
+        }
+
+        private void WriteResponse(Socket client, HttpStatusCode code, string body) 
+        {
+            WriteResponse(client, code, Encoding.UTF8.GetBytes(body));
+        }
+        
+        private void WriteResponse(Socket client, HttpStatusCode code, byte [] body) 
+        {
+            if(!client.Connected) {
+                return;
+            }
+            
+            string headers = String.Empty;
+            headers += String.Format("HTTP/1.1 {0} {1}\r\n", (int)code, code.ToString());
+            headers += String.Format("Content-Length: {0}\r\n", body.Length);
+            headers += "Content-Type: text/html\r\n";
+            headers += "Connection: close\r\n";
+            headers += "\r\n";
+            
+            using(BinaryWriter writer = new BinaryWriter(new NetworkStream(client, false))) {
+                writer.Write(Encoding.UTF8.GetBytes(headers));
+                writer.Write(body);
+            }
+            
+            client.Close();
+        }
+
+        private void WriteResponseStream(Socket client, Stream response, long length, string filename)
+        {
+            using(BinaryWriter writer = new BinaryWriter(new NetworkStream(client, false))) {
+                string headers = "HTTP/1.1 200 OK\r\n";
+
+                if(length > 0) {
+                    headers += String.Format("Content-Length: {0}\r\n", length);
+                }
+                
+                if(filename != null) {
+                    headers += String.Format("Content-Disposition: attachment; filename=\"{0}\"\r\n",
+                        filename.Replace("\"", "\\\""));
+                }
+                
+                headers += "Connection: close\r\n";
+                headers += "\r\n";
+                
+                writer.Write(Encoding.UTF8.GetBytes(headers));
+
+                using(BinaryReader reader = new BinaryReader(response)) {
+                    while(true) {
+                        byte [] buffer = reader.ReadBytes(ChunkLength);
+                        if(buffer == null) {
+                            break;
+                        }
+                        
+                        writer.Write(buffer);
+                        
+                        if(buffer.Length < ChunkLength) {
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        
+        private static string GetHtmlHeader(string title)
+        {
+            return String.Format("<html><head><title>{0} - Banshee DAAP Browser</title></head><body><h1>{0}</h1>", 
+                title);
+        }
+        
+        private static string GetHtmlFooter()
+        {
+            return String.Format("<hr /><address>Generated on {0} by " + 
+                "Banshee DAAP Plugin (<a href=\"http://banshee-project.org\";>http://banshee-project.org</a>)",
+                DateTime.Now.ToString());
+        }
+
+        public ushort Port {
+            get { 
+                return port;
+            }
+        }
+
+        private static IPAddress local_address = IPAddress.Parse("127.0.0.1");
+        public IPAddress IPAddress {
+            get {
+                return local_address;
+            }
+        }
+        
+        public string HttpBaseAddress {
+            get {
+                return String.Format("http://{0}:{1}/";, IPAddress, Port);
+            }
+        }
+    }
+}

Modified: trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapService.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapService.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapService.cs	Tue Jun 24 19:00:45 2008
@@ -41,10 +41,15 @@
     public class DaapService : IExtensionService, IDisposable
     {
         private ServiceLocator locator;
+        private static DaapProxyWebServer proxy_server;
         
         private DaapContainerSource container;
         private Dictionary<string, DaapSource> source_map;
         
+        internal static DaapProxyWebServer ProxyServer {
+            get { return proxy_server; }
+        }
+        
         void IExtensionService.Initialize ()
         {
             // Add the source, even though its empty, so that the user sees the
@@ -61,6 +66,9 @@
             locator.Removed += OnServiceRemoved;
             locator.ShowLocalServices = true;
             locator.Start ();
+            
+            proxy_server = new DaapProxyWebServer ();
+            proxy_server.Start ();
         }
         
         public void Dispose ()
@@ -72,6 +80,11 @@
                 locator = null;
             }
             
+            if (proxy_server != null) {
+                proxy_server.Stop ();
+                proxy_server = null;
+            }
+            
             // Dispose any remaining child sources
             foreach (KeyValuePair <string, DaapSource> kv in source_map) {
                 kv.Value.Disconnect (true);
@@ -79,7 +92,7 @@
             }
             
             if (container != null) {
-                ServiceManager.SourceManager.RemoveSource (container, false);
+                ServiceManager.SourceManager.RemoveSource (container, true);
                 container = null;
             }
             
@@ -105,6 +118,7 @@
             }
             
             container.AddChildSource (source);
+            source.NotifyUser ();
         }
         
         private void OnServiceRemoved (object o, ServiceArgs args)

Modified: trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapSource.cs	Tue Jun 24 19:00:45 2008
@@ -52,9 +52,8 @@
         public DAAP.Database Database {
             get { return database; }
         }
-        
+
         private bool is_activating;
-        private int playlistid;
         
         public DaapSource (DAAP.Service service) : base (Catalog.GetString ("Music Share"), service.Name, 
                                                     (service.Address.ToString () + service.Port).Replace (":", "").Replace (".", ""), 300)
@@ -63,10 +62,11 @@
             Properties.SetString ("UnmapSourceActionLabel", Catalog.GetString ("Disconnect"));
             Properties.SetString ("UnmapSourceActionIconName", "gtk-disconnect");
             
+            SupportsPlaylists = false;
+            SavedCount = 0;
             UpdateIcon ();
             
             AfterInitialized ();
-            playlistid = this.DbId;
         }
         
         private void UpdateIcon ()
@@ -89,8 +89,6 @@
             
             SetStatus (String.Format (Catalog.GetString ("Connecting to {0}"), service.Name), false);
             
-            Console.WriteLine ("Connecting to {0}:{1}", service.Address, service.Port);
-            
             ThreadAssist.Spawn (delegate {
                 try {
                     client = new DAAP.Client (service);
@@ -120,7 +118,7 @@
                         ServiceManager.PlayerEngine.Close ();
                     }
                 }
-            } catch { }
+            } catch {}
             
             // Remove tracks associated with this source, since we don't want
             // them after we unmap - we'll refetch.
@@ -137,6 +135,9 @@
             }
             
             if (database != null) {
+                try {
+                    DaapService.ProxyServer.UnregisterDatabase (database);
+                } catch {}
                 database.TrackAdded -= OnDatabaseTrackAdded;
                 database.TrackRemoved -= OnDatabaseTrackRemoved;
                 database = null;
@@ -190,6 +191,7 @@
         {
             if (database == null && client.Databases.Count > 0) {
                 database = client.Databases[0];
+                DaapService.ProxyServer.RegisterDatabase (database);
                 database.TrackAdded += OnDatabaseTrackAdded;
                 database.TrackRemoved += OnDatabaseTrackRemoved;
                 
@@ -199,6 +201,7 @@
                 DaapTrackInfo daap_track = null;
                 foreach (DAAP.Track track in database.Tracks) {
                     daap_track = new DaapTrackInfo (track, this);
+                    // Only notify once every 250 tracks
                     daap_track.Save (++count % 250 == 0);
                 }
                 
@@ -222,9 +225,8 @@
         private void AddPlaylistSources ()
         {
             foreach (DAAP.Playlist pl in database.Playlists) {
-                DaapPlaylistSource source = new DaapPlaylistSource (pl, playlistid, this);
+                DaapPlaylistSource source = new DaapPlaylistSource (pl, this);
                 AddChildSource (source);
-                playlistid ++;
             }
         }
         

Modified: trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapTrackInfo.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapTrackInfo.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Banshee.Daap/DaapTrackInfo.cs	Tue Jun 24 19:00:45 2008
@@ -53,28 +53,17 @@
             TrackNumber = track.TrackNumber;
             Year = track.Year;
             Duration = track.Duration;
-            MimeType = track.Format;
+            MimeType = String.Format ("taglib/{0}", track.Format);
             ExternalId = track.Id;
             
             PrimarySource = source;
             
-            string session_id = String.Empty;
-            if (source.Database.Client.Fetcher.SessionId != 0) {
-                session_id = String.Format ("?session-id={0}", source.Database.Client.Fetcher.SessionId);
-            }
-
-            string uri = String.Format ("http://{0}:{1}/databases/{2}/items/{3}.{4}{5}";,
-                                        source.Database.Client.Address.ToString (),
-                                        source.Database.Client.Port,
-                                        source.Database.Id,
-                                        track.Id,
-                                        track.Format,
-                                        session_id);
+            Uri = new SafeUri (String.Format (
+                "{0}{1}/{2}", DaapService.ProxyServer.HttpBaseAddress, source.Database.GetHashCode (), track.Id
+            ));
             
-            Uri = new SafeUri (uri);
-            
-            //this.IsLive = true;
-            this.CanSaveToDatabase = false;
+            //this.IsLive = false;
+            //this.CanSaveToDatabase = false;
         }
     }
 }

Modified: trunk/banshee/src/Extensions/Banshee.Daap/Daap/Database.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Daap/Daap/Database.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Daap/Database.cs	Tue Jun 24 19:00:45 2008
@@ -125,23 +125,24 @@
             get { return client; }
         }
 
-        private Database () {
+        private Database ()
+        {
             this.id = nextid++;
         }
 
-        public Database (string name) : this () {
+        public Database (string name) : this ()
+        {
             this.Name = name;
         }
 
-        internal Database (Client client, ContentNode dbNode) : this () {
+        internal Database (Client client, ContentNode dbNode) : this ()
+        {
             this.client = client;
-
             Parse (dbNode);
         }
 
         private void Parse (ContentNode dbNode) {
             foreach (ContentNode item in (ContentNode[]) dbNode.Value) {
-
                 switch (item.Name) {
                 case "dmap.itemid":
                     id = (int) item.Value;

Modified: trunk/banshee/src/Extensions/Banshee.Daap/Makefile.am
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.Daap/Makefile.am	(original)
+++ trunk/banshee/src/Extensions/Banshee.Daap/Makefile.am	Tue Jun 24 19:00:45 2008
@@ -7,6 +7,7 @@
 	Banshee.Daap/DaapContainerSource.cs \
 	Banshee.Daap/DaapLoginDialog.cs \
 	Banshee.Daap/DaapPlaylistSource.cs \
+	Banshee.Daap/DaapProxyWebServer.cs \
 	Banshee.Daap/DaapService.cs \
 	Banshee.Daap/DaapSource.cs \
 	Banshee.Daap/DaapTrackInfo.cs \
@@ -28,8 +29,8 @@
 	Daap/Utility.cs
 
 RESOURCES =  \
-	Daap/content-codes \
-	Resources/Banshee.Daap.addin.xml
+	Banshee.Daap.addin.xml \
+	Daap/content-codes
 
 if DAAP_ENABLED
 include $(top_srcdir)/build/build.mk



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