Index: src/Banshee.Plugins/Daap/DaapContainerSource.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Plugins/Daap/DaapContainerSource.cs,v
retrieving revision 1.1
diff -u -8 -p -r1.1 DaapContainerSource.cs
--- src/Banshee.Plugins/Daap/DaapContainerSource.cs	23 Oct 2006 05:33:09 -0000	1.1
+++ src/Banshee.Plugins/Daap/DaapContainerSource.cs	23 Oct 2006 14:12:39 -0000
@@ -30,33 +30,107 @@ using System;
 using System.IO;
 using System.Collections.Generic;
 using System.Collections;
 using Mono.Unix;
 using DAAP;
 
 using Banshee.Base;
 using Banshee.Sources;
+using Banshee.Widgets;
 
 namespace Banshee.Plugins.Daap
 {
-    public class DaapContainerSource : Source
+    public class DaapContainerSource : Source, IImportable
     {
-
+        private List<TrackInfo> tracks = new List<TrackInfo> ();
+        private ActionButton connect_button;
+        
         public DaapContainerSource() : base("Shared Music", 300)
         {
+            connect_button = new ActionButton (Globals.ActionManager ["DaapConnectAll"]);
+        }
+        
+        public override void Activate()
+        {
+            InterfaceElements.ActionButtonBox.PackStart (connect_button, false, false, 0);
+        }
+        public override void Deactivate()
+        {
+            InterfaceElements.ActionButtonBox.Remove (connect_button);
+        }
+        
+        internal void MergeSource (object o, EventArgs args)
+        {
+            DaapSource source = o as DaapSource;
+            foreach (TrackInfo track in source.Tracks) {
+                tracks.Add(track);
+            }
+            OnUpdated();
+        }
+        
+        internal void UnmergeSource (object o, EventArgs args)
+        {
+            DaapSource source = o as DaapSource;
+            foreach (TrackInfo track in source.Tracks) {
+                tracks.Remove(track);
+  			}
+            OnUpdated();
+        }
+        
+        internal void UpdateSource (object o, EventArgs args)
+        {
+            DaapSource source = o as DaapSource;
+            UnmergeSource(source, null);
+            MergeSource(source, null);
+        }
+        
+        public override IEnumerable<TrackInfo> Tracks {
+            get { return tracks; }
         }
 
         public override int Count {
-            get { return DaapCore.ServerCount; }
+            get { return tracks.Count; }
         }
 
         private static Gdk.Pixbuf icon = IconThemeUtils.LoadIcon(22, "network-server", Gtk.Stock.Network); 
 
         public override Gdk.Pixbuf Icon {
             get { return icon; }
         }
         
+        public override bool Unmap()
+        {
+            DaapCore.DisconnectAll();
+            return true;
+        }
+        
+        public override string UnmapIcon {
+            get { return Gtk.Stock.Disconnect; }
+        }
+        
+        public override string UnmapLabel {
+            get { return Catalog.GetString("Disconnect From All"); }
+        }
+        
         public override bool AutoExpand {
             get { return false; }
+        }
+        
+        public void Import(IEnumerable<TrackInfo> tracks)
+        {
+            Import(tracks, null);
+        }
+        
+        private DaapImporter importer;
+        public void Import(IEnumerable<TrackInfo> tracks, PlaylistSource playlist)
+        {
+            if(importer == null)
+            {
+                importer = new DaapImporter(Name);
+                importer.Finished += delegate {
+                    importer = null;
+                };
+            }
+            importer.Import(tracks, playlist);
         }
     }
 }
Index: src/Banshee.Plugins/Daap/DaapCore.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Plugins/Daap/DaapCore.cs,v
retrieving revision 1.14
diff -u -8 -p -r1.14 DaapCore.cs
--- src/Banshee.Plugins/Daap/DaapCore.cs	23 Oct 2006 05:33:09 -0000	1.14
+++ src/Banshee.Plugins/Daap/DaapCore.cs	23 Oct 2006 14:12:40 -0000
@@ -26,39 +26,51 @@
  *  DEALINGS IN THE SOFTWARE.
  */
  
 using System;
 using System.IO;
 using System.Collections;
 using Mono.Unix;
 using DAAP;
+using Gtk;
 
 using Banshee.Base;
 using Banshee.Sources;
 
 namespace Banshee.Plugins.Daap
 {
     internal static class DaapCore
     {
         private static DaapPlugin plugin;
         private static Server server;
         private static DAAP.Database database;
         private static ServiceLocator locator;
         private static DaapProxyWebServer proxy_server;
         private static Hashtable source_map;
         private static int collision_count;
         private static DaapContainerSource container_source;
+        private static ActionGroup actions;
         
         private static bool initial_db_committed = false;
         
         internal static void Initialize(DaapPlugin plugin)
         {
             DaapCore.plugin = plugin;
             
+            actions = new ActionGroup("Daap");
+            actions.Add (new ActionEntry [] {
+                new ActionEntry ("DaapConnectAll", Stock.Connect,
+                "Connect to Everyone", null,
+                "Try to establish a connection with every availible " +
+                "shared music source",
+                OnDaapConnectAllHandler)
+            });
+            Globals.ActionManager.UI.InsertActionGroup(actions, 0);
+            
             source_map = new Hashtable();
             locator = new ServiceLocator();
             locator.Found += OnServiceFound;
             locator.Removed += OnServiceRemoved;
             locator.ShowLocalServices = true;
             locator.Start();
             
             proxy_server = new DaapProxyWebServer();
@@ -85,16 +97,40 @@ namespace Banshee.Plugins.Daap
             
             if(Globals.Library.IsLoaded) {
                 LoadInitialServerDatabase();
             } else {
                 Globals.Library.Reloaded += OnLibraryReloaded;
             }
         }
         
+        private static void OnDaapConnectAllHandler(object sender, EventArgs args)
+        {
+            ConnectAll();
+        }
+        
+        public static void ConnectAll()
+        {
+            foreach (DictionaryEntry entry in source_map) {
+                DaapSource source = entry.Value as DaapSource;
+                if (!source.IsClientLoggedIn) {
+                    source.Activate(true);
+                }
+            }
+        }
+        public static void DisconnectAll()
+        {
+            foreach (DictionaryEntry entry in source_map) {
+                DaapSource source = entry.Value as DaapSource;
+                if (source.IsClientLoggedIn) {
+                    source.Unmap();
+                }
+            }
+        }
+        
         internal static void Dispose()
         {
             if(locator != null) {
                 locator.Stop();
                 locator.Found -= OnServiceFound;
                 locator.Removed -= OnServiceRemoved;
                 locator = null;
             }
@@ -134,16 +170,19 @@ namespace Banshee.Plugins.Daap
                 
                 while (source_map.Contains(service_name))
                     service_name = args.Service.Name + " [" + ++collision + "]";
                 source_map.Add(service_name, source);
                 if(source_map.Count == 1) {
                     container_source = new DaapContainerSource();
                     SourceManager.AddSource(container_source);
                 }
+                source.ClientLoggedIn += container_source.MergeSource;
+                source.ClientLoggedOut += container_source.UnmergeSource;
+                source.ClientChanged += container_source.UpdateSource;
                 container_source.AddChildSource(source);
                 
             } catch(InvalidSourceException) {
             }
         }
         
         private static void OnServiceRemoved(object o, ServiceArgs args)
         {
Index: src/Banshee.Plugins/Daap/DaapPlaylistSource.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Plugins/Daap/DaapPlaylistSource.cs,v
retrieving revision 1.1
diff -u -8 -p -r1.1 DaapPlaylistSource.cs
--- src/Banshee.Plugins/Daap/DaapPlaylistSource.cs	21 Sep 2006 19:44:38 -0000	1.1
+++ src/Banshee.Plugins/Daap/DaapPlaylistSource.cs	23 Oct 2006 14:12:40 -0000
@@ -33,17 +33,17 @@ using System.Collections;
 using Mono.Unix;
 using DAAP;
 
 using Banshee.Base;
 using Banshee.Sources;
 
 namespace Banshee.Plugins.Daap
 {
-    public class DaapPlaylistSource : ChildSource
+    public class DaapPlaylistSource : ChildSource, IImportable, IImportSource
     {
         private DAAP.Database db;
         private DAAP.Playlist pl;
         private List<TrackInfo> tracks = new List<TrackInfo> ();
 
         public override IEnumerable<TrackInfo> Tracks {
             get { return tracks; }
         }
@@ -55,10 +55,33 @@ namespace Banshee.Plugins.Daap
         public DaapPlaylistSource(DAAP.Database db, DAAP.Playlist pl) : base(pl.Name, 300)
         {
             this.db = db;
             this.pl = pl;
             foreach (Track t in pl.Tracks) {
                 tracks.Add (new DaapTrackInfo (t, db));
             }
         }
-    }
+    
+    	public void Import()
+        {
+            Import(Tracks);
+        }
+        
+        public void Import(IEnumerable<TrackInfo> tracks)
+        {
+            Import(tracks, null);
+        }
+        
+        private DaapImporter importer;
+        public void Import(IEnumerable<TrackInfo> tracks, PlaylistSource playlist)
+        {
+            if(importer == null)
+            {
+                importer = new DaapImporter(Name);
+                importer.Finished += delegate {
+                    importer = null;
+                };
+            }
+            importer.Import(tracks, playlist);
+        }
+	}
 }
Index: src/Banshee.Plugins/Daap/DaapSource.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Plugins/Daap/DaapSource.cs,v
retrieving revision 1.11
diff -u -8 -p -r1.11 DaapSource.cs
--- src/Banshee.Plugins/Daap/DaapSource.cs	23 Oct 2006 05:33:09 -0000	1.11
+++ src/Banshee.Plugins/Daap/DaapSource.cs	23 Oct 2006 14:12:40 -0000
@@ -41,43 +41,55 @@ namespace Banshee.Plugins.Daap
     
     public class DaapSource : ChildSource, IImportable, IImportSource
     {        
         private Service service;
         private Client client;
         private DAAP.Database database;
         private DatabaseProxy database_proxy;
         private bool is_activating;
+        private bool is_logged_in;
+        
+        public event EventHandler ClientLoggedIn;
+        public event EventHandler ClientLoggedOut;
+        public event EventHandler ClientChanged;
         
         public DaapSource(Service service) : base(service.Name, 300)
         {
             this.service = service;
             is_activating = false;
             database_proxy = new DatabaseProxy();
         }
         
         public override void Activate()
         {
+            Activate(false);
+        }
+        
+        public void Activate(bool silent)
+        {
             if(client != null || is_activating) {
             	return;
             }
             is_activating = true;
             Console.WriteLine("Connecting to DAAP share: " + service);
             ThreadAssist.Spawn(delegate {
                 client = new Client(service);
                 client.Updated += OnClientUpdated;
                 try {
                     if(client.AuthenticationMethod == AuthenticationMethod.None) {
                         client.Login();
-                    } else {
+                    } else if (!silent) {
                         ThreadAssist.ProxyToMain(PromptLogin);
                     }
                 } catch(Exception e) {
-                    LogCore.Instance.PushError(Catalog.GetString("Cannot login to DAAP share"),
-                        e.Message);
+                    if(!silent) {
+                        LogCore.Instance.PushError(Catalog.GetString("Cannot login to DAAP share"),
+                            e.Message);
+                    }
                 }
                
                 is_activating = false;
             });
         }
 
         private void AddPlaylistSources ()
         {
@@ -113,39 +125,61 @@ namespace Banshee.Plugins.Daap
                 AuthenticatedLogin(dialog.Username, dialog.Password);
             } else {
                 Dispose();
             }
 
             dialog.Destroy();
         }
         
+        protected void OnClientLoggedIn()
+        {
+            if (ClientLoggedIn != null) {
+                ClientLoggedIn(this, null);
+            }
+        }
+        
+        protected void OnClientLoggedOut()
+        {
+            if (ClientLoggedOut != null) {
+                ClientLoggedOut(this, null);
+            }
+        }
+        
+        protected void OnClientChanged()
+        {
+            if (ClientChanged != null) {
+                ClientChanged(this, null);
+            }
+        }
+        
         protected override void OnDispose()
         {
             Unmap();
         }
 
         internal bool Disconnect (bool logout)
         {
+            OnClientLoggedOut();
             if(client != null) {
                 if (logout)
                     client.Logout();
 
                 client.Dispose();
                 client = null;
                 database = null;
             }
             
             if(database != null) {
                 database.TrackAdded -= OnDatabaseTrackAdded;
                 database.TrackRemoved -= OnDatabaseTrackRemoved;
                 DaapCore.ProxyServer.UnregisterDatabase(database);
                 database = null;
             }
-
+            is_logged_in = false;
             ClearChildSources ();
             
             return true;
         }
         
         public override bool Unmap()
         {
             return Disconnect (true);
@@ -153,26 +187,36 @@ namespace Banshee.Plugins.Daap
         
         public override string UnmapIcon {
             get { return Gtk.Stock.Disconnect; }
         }
 
         public override string UnmapLabel {
             get { return Catalog.GetString("Disconnect"); }
         }
+        
+        public bool IsClientLoggedIn {
+            get { return is_logged_in; }
+        }
 
         private void OnClientUpdated(object o, EventArgs args)
         {
             if(database == null && client.Databases.Count > 0) {
                 database = client.Databases[0];
                 database.TrackAdded += OnDatabaseTrackAdded;
                 database.TrackRemoved += OnDatabaseTrackRemoved;
                 database_proxy.Database = database;
                 DaapCore.ProxyServer.RegisterDatabase(database);
                 AddPlaylistSources ();
+                if (!is_logged_in) {
+                    OnClientLoggedIn();
+                } else {
+                    OnClientChanged();
+                }
+                is_logged_in = true;
             }
             
             Name = client.Name;
             
             ThreadAssist.ProxyToMain(delegate {
                 OnUpdated();
             });
         }
@@ -205,29 +249,70 @@ namespace Banshee.Plugins.Daap
         }
         
         public override bool AutoExpand {
             get { return false; }
         }
 
         public void Import()
         {
-            Activate ();
-
-            // omg this is so crappy
-            while (is_activating)
-                System.Threading.Thread.Sleep (1);
-            
+            if (!is_logged_in) {
+                ClientLoggedIn += ContinueImport;
+                Activate();
+                return;
+            }
             Import(Tracks);
         }
         
-        private QueuedOperationManager import_manager;
+        private void ContinueImport(object o, EventArgs args)
+        {
+            ClientLoggedIn -= ContinueImport;
+            Import(Tracks);
+        }
         
+        public void Import(IEnumerable<TrackInfo> tracks)
+        {
+            Import(tracks, null);
+        }
+        
+        private DaapImporter importer;
         public void Import(IEnumerable<TrackInfo> tracks, PlaylistSource playlist)
         {
+            if(importer == null)
+            {
+                importer = new DaapImporter(Name);
+                importer.Finished += delegate {
+                    importer = null;
+                };
+            }
+            importer.Import(tracks, playlist);
+        }        
+    }
+    
+    internal class DaapImporter
+    {
+        private string Name;
+        private Gdk.Pixbuf Icon = IconThemeUtils.LoadIcon(22, "network-server", Gtk.Stock.Network);
+        private QueuedOperationManager import_manager;
+        public event EventHandler Finished;
+        
+        private void OnFinished()
+        {
+            if(Finished != null) {
+                Finished(this, null);
+            }
+        }
+        
+        internal DaapImporter (string name)
+        {
+            Name = name;
+        }
+        
+        internal void Import(IEnumerable<TrackInfo> tracks, PlaylistSource playlist)
+        {
             if(playlist != null && playlist.Count == 0) {
                 playlist.Rename(PlaylistUtil.GoodUniqueName(tracks));
                 playlist.Commit();
             }
         
             if(import_manager == null) {
                 import_manager = new QueuedOperationManager();
                 import_manager.HandleActveUserEvent = false;
@@ -235,31 +320,27 @@ namespace Banshee.Plugins.Daap
                 import_manager.UserEvent.CancelMessage = String.Format(Catalog.GetString(
                     "You are currently importing from {0}. Would you like to stop it?"), Name);
                 import_manager.UserEvent.Icon = Icon;
                 import_manager.UserEvent.Header = String.Format(Catalog.GetString("Copying from {0}"), Name);
                 import_manager.UserEvent.Message = Catalog.GetString("Scanning...");
                 import_manager.OperationRequested += OnImportOperationRequested;
                 import_manager.Finished += delegate {
                     import_manager = null;
+                    OnFinished();
                 };
             }
 
             foreach(TrackInfo track in tracks) {
                 if(playlist == null) {
                     import_manager.Enqueue(track);
                 } else {
                     import_manager.Enqueue(new KeyValuePair<TrackInfo, PlaylistSource>(track, playlist));
                 }
             }
-        }
-        
-        public void Import(IEnumerable<TrackInfo> tracks)
-        {
-            Import(tracks, null);
         }
         
         private void OnImportOperationRequested(object o, QueuedOperationArgs args)
         {
             DaapTrackInfo track = null;
             PlaylistSource playlist = null;
             
             if(args.Object is DaapTrackInfo) {
