Index: src/Banshee.Base/ChildSource.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Base/ChildSource.cs,v
retrieving revision 1.2
diff -u -p -r1.2 ChildSource.cs
--- src/Banshee.Base/ChildSource.cs	3 Jul 2006 00:27:39 -0000	1.2
+++ src/Banshee.Base/ChildSource.cs	19 Oct 2006 23:57:24 -0000
@@ -38,16 +38,6 @@ namespace Banshee.Sources
         {
         }
 
-        public override void AddChildSource(ChildSource source)
-        {
-            throw new Exception("Cannot add a child source to a child source!");
-        }
-
-        public override void RemoveChildSource(ChildSource source)
-        {
-            throw new Exception("Cannot remove a child source from a child source!");
-        }
-
         public void SetParentSource(Source source)
         {
             parent = source;
Index: src/Banshee.Base/Source.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Base/Source.cs,v
retrieving revision 1.19
diff -u -p -r1.19 Source.cs
--- src/Banshee.Base/Source.cs	4 Sep 2006 22:38:00 -0000	1.19
+++ src/Banshee.Base/Source.cs	19 Oct 2006 23:57:25 -0000
@@ -223,45 +223,57 @@ namespace Banshee.Sources
                 copy.Reverse ();
             }
 
-            foreach(ChildSource child in copy) {
-                AddChildSource (child);
+            lock(Children)
+            {
+	            foreach(ChildSource child in copy) {
+	                AddChildSource (child);
+	            }
             }
         }
         
         public virtual void AddChildSource(ChildSource source)
         {
-            source.SetParentSource(this);
-            child_sources.Add(source);
-        
-            SourceEventHandler handler = ChildSourceAdded;
-            if(handler != null) {
-                SourceEventArgs evargs = new SourceEventArgs();
-                evargs.Source = source;
-                handler(evargs);
+            lock(Children)
+            {
+	            source.SetParentSource(this);
+	            child_sources.Add(source);
+	        
+	            SourceEventHandler handler = ChildSourceAdded;
+	            if(handler != null) {
+	                SourceEventArgs evargs = new SourceEventArgs();
+	                evargs.Source = source;
+	                handler(evargs);
+	            }
             }
         }
 
         public virtual void RemoveChildSource(ChildSource source)
         {
-            child_sources.Remove(source);
-            
-            if(SourceManager.ActiveSource == source) {
-                SourceManager.SetActiveSource(SourceManager.DefaultSource);
-            }
+            lock(Children)
+            {
+	            child_sources.Remove(source);
+	            
+	            if(SourceManager.ActiveSource == source) {
+	                SourceManager.SetActiveSource(SourceManager.DefaultSource);
+	            }
 
-            SourceEventHandler handler = ChildSourceRemoved;
-            if(handler != null) {
-                SourceEventArgs evargs = new SourceEventArgs();
-                evargs.Source = source;
-                handler(evargs);
-            }
+	            SourceEventHandler handler = ChildSourceRemoved;
+	            if(handler != null) {
+	                SourceEventArgs evargs = new SourceEventArgs();
+	                evargs.Source = source;
+	                handler(evargs);
+	            }
+	        }
         }
         
         public virtual void ClearChildSources()
         {
-            while(child_sources.Count > 0) {
-                RemoveChildSource(child_sources[0] as ChildSource);
-            }
+            lock(Children)
+            {
+	            while(child_sources.Count > 0) {
+	                RemoveChildSource(child_sources[0] as ChildSource);
+				}
+			}
         }
         
         public virtual void SourceDrop(Source source)
Index: src/Banshee.Base/Gui/SourceView.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Base/Gui/SourceView.cs,v
retrieving revision 1.57
diff -u -p -r1.57 SourceView.cs
--- src/Banshee.Base/Gui/SourceView.cs	27 Sep 2006 16:02:15 -0000	1.57
+++ src/Banshee.Base/Gui/SourceView.cs	19 Oct 2006 23:57:25 -0000
@@ -133,32 +133,30 @@ namespace Banshee.Gui
             };
         }
 
-        // FIXME: This is lame and could use some recusrion instead (Lukas)
         private TreeIter FindSource(Source source)
         {
-            for(int i = 0, m = store.IterNChildren(); i < m; i++) {
-                TreeIter iter = TreeIter.Zero;
-                if(!store.IterNthChild(out iter, i)) {
-                    continue;
-                }
-                
-                if((store.GetValue(iter, 0) as Source) == source) {
-                    return iter;
-                }
+			TreeIter iter = TreeIter.Zero;
+			store.GetIterFirst(out iter);
+			return FindSource(source, iter);
+        }
         
-                for(int j = 0, n = store.IterNChildren(iter); j < n; j++) {
-                    TreeIter citer = TreeIter.Zero;
-                    if(!store.IterNthChild(out citer, iter, j)) {
-                        continue;
-                    }
-    
-                    if((store.GetValue(citer, 0) as Source) == source) {
-                        return citer;
-                    }
+        private TreeIter FindSource(Source source, TreeIter iter)
+        {
+        	if (!store.IterIsValid(iter))
+        		return TreeIter.Zero;
+        	do {
+        		if((store.GetValue(iter, 0) as Source) == source)
+                	return iter;
+                if(store.IterHasChild(iter)) {
+                	TreeIter citer = TreeIter.Zero;
+                	store.IterChildren(out citer, iter);
+                	TreeIter result = FindSource(source, citer);
+                	if (!result.Equals(TreeIter.Zero))
+                		return result;
                 }
-            }
-
-            return TreeIter.Zero;
+        	}
+        	while (store.IterNext(ref iter));
+        	return TreeIter.Zero;
         }
         
         private void AddSource(Source source)
@@ -168,28 +166,31 @@ namespace Banshee.Gui
 
         private void AddSource(Source source, int position)
         {
-            if(FindSource(source).Equals(TreeIter.Zero)) {
-                TreeIter iter = store.InsertNode(position);
-                store.SetValue(iter, 0, source);
-
-                foreach (ChildSource s in source.Children) {
-                    TreeIter i = store.AppendNode(iter);
-                    store.SetValue(i, 0, s);
-                }
+            AddSource(source, position, TreeIter.Zero);
+        }
         
-                source.ChildSourceAdded += delegate(SourceEventArgs e) {
-                    TreeIter i = store.AppendNode(iter);
-                    store.SetValue(i, 0, e.Source);
-                    Expand(iter);
-                    UpdateView ();
-                };
-
-                source.ChildSourceRemoved += delegate(SourceEventArgs e) {
-                    RemoveSource(e.Source);
-                };
-
-                Expand(iter);
-            }
+        private void AddSource(Source source, int position, TreeIter parent)
+        {
+        	if(!FindSource(source).Equals(TreeIter.Zero))
+        		return;
+        		
+			TreeIter iter = (parent.Equals(TreeIter.Zero))
+				? store.InsertNode(position) : iter = store.AppendNode(parent);
+			store.SetValue(iter, 0, source);
+
+			lock(source.Children) {
+				foreach (ChildSource s in source.Children) {
+					AddSource(s, position, iter);
+				}
+			}
+
+			source.ChildSourceAdded += delegate(SourceEventArgs e) {
+				AddSource(e.Source, position, iter);
+			};
+
+			source.ChildSourceRemoved += delegate(SourceEventArgs e) {
+				RemoveSource(e.Source);
+			};
 
             UpdateView();
         }
@@ -216,7 +217,7 @@ namespace Banshee.Gui
             foreach(Source source in SourceManager.Sources) {
                 AddSource (source);
             }
-        } 
+        }
 
         private bool UpdateView()
         {
Index: src/Banshee.Plugins/Daap/DaapAllSource.cs
===================================================================
RCS file: src/Banshee.Plugins/Daap/DaapAllSource.cs
diff -N src/Banshee.Plugins/Daap/DaapAllSource.cs
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/Banshee.Plugins/Daap/DaapAllSource.cs	19 Oct 2006 23:57:25 -0000
@@ -0,0 +1,70 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Collections;
+using Mono.Unix;
+using DAAP;
+using Gtk;
+
+using Banshee.Base;
+using Banshee.Widgets;
+using Banshee.Sources;
+
+namespace Banshee.Plugins.Daap
+{
+	public class DaapAllSource : Source
+	{
+		private ActionButton connect_button;
+        private List<TrackInfo> tracks = new List<TrackInfo> ();
+        
+        public DaapAllSource() : 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 (DaapSource source)
+        {
+       		foreach (TrackInfo track in source.Tracks) {
+  				tracks.Add(track);
+  			}
+  			OnUpdated();
+        }
+        
+        internal void UnMergeSource (DaapSource source)
+        {
+        	foreach (TrackInfo track in source.Tracks) {
+  				tracks.Remove(track);
+  			}
+  			OnUpdated();
+        }
+        
+        internal void UpdateSource (DaapSource source)
+        {
+        	UnMergeSource(source);
+        	MergeSource(source);
+        }
+        
+        public override IEnumerable<TrackInfo> Tracks {
+            get { return tracks; }
+        }
+        
+        public override int Count {
+        	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; }
+        }
+	}
+}
Index: src/Banshee.Plugins/Daap/DaapCore.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Plugins/Daap/DaapCore.cs,v
retrieving revision 1.13
diff -u -p -r1.13 DaapCore.cs
--- src/Banshee.Plugins/Daap/DaapCore.cs	25 Sep 2006 17:04:39 -0000	1.13
+++ src/Banshee.Plugins/Daap/DaapCore.cs	19 Oct 2006 23:57:26 -0000
@@ -31,6 +31,7 @@ using System.IO;
 using System.Collections;
 using Mono.Unix;
 using DAAP;
+using Gtk;
 
 using Banshee.Base;
 using Banshee.Sources;
@@ -46,6 +47,8 @@ namespace Banshee.Plugins.Daap
         private static DaapProxyWebServer proxy_server;
         private static Hashtable source_map;
         private static int collision_count;
+        private static DaapAllSource all_source;
+        private static ActionGroup actions;
         
         private static bool initial_db_committed = false;
         
@@ -53,6 +56,19 @@ namespace Banshee.Plugins.Daap
         {
             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);
+            
+            all_source = new DaapAllSource();
+            SourceManager.AddSource(all_source);
+            
             source_map = new Hashtable();
             locator = new ServiceLocator();
             locator.Found += OnServiceFound;
@@ -90,6 +106,22 @@ namespace Banshee.Plugins.Daap
             }
         }
         
+        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.IsLoggedIn) {
+		       			source.Activate(true);
+		       		}
+	       	}
+        }
+        
         internal static void Dispose()
         {
             if(locator != null) {
@@ -124,7 +156,7 @@ namespace Banshee.Plugins.Daap
                 return;
             
             try {
-                Source source = new DaapSource(args.Service);
+                DaapSource source = new DaapSource(args.Service);
                 int collision = 0;
                 string service_name = args.Service.Name;
                 
@@ -135,7 +167,11 @@ namespace Banshee.Plugins.Daap
                 while (source_map.Contains(service_name))
                     service_name = args.Service.Name + " [" + ++collision + "]";
                 source_map.Add(service_name, source);
-                SourceManager.AddSource(source);
+                all_source.AddChildSource(source);
+                source.LoggedIn += all_source.MergeSource;
+                source.LoggedOut += all_source.UnMergeSource;
+                source.Changed += all_source.UpdateSource;
+                
             } catch(InvalidSourceException) {
             }
         }
@@ -146,10 +182,10 @@ namespace Banshee.Plugins.Daap
             if(source == null) {
                 return;
             }
-
+            
             source.Disconnect (false);
             source.Dispose();
-            SourceManager.RemoveSource(source);
+            all_source.RemoveChildSource(source);
             source_map.Remove(args.Service.Name);
         }
         
@@ -255,6 +291,11 @@ namespace Banshee.Plugins.Daap
             get {
                 return server.IsRunning;
             }
+        }
+        
+        internal static Hashtable SourceMap
+        {
+        	get { return source_map; }
         }
     }
 }
Index: src/Banshee.Plugins/Daap/DaapSource.cs
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Plugins/Daap/DaapSource.cs,v
retrieving revision 1.10
diff -u -p -r1.10 DaapSource.cs
--- src/Banshee.Plugins/Daap/DaapSource.cs	25 Sep 2006 16:42:13 -0000	1.10
+++ src/Banshee.Plugins/Daap/DaapSource.cs	19 Oct 2006 23:57:26 -0000
@@ -38,13 +38,36 @@ using Banshee.Sources;
 
 namespace Banshee.Plugins.Daap
 {
-    public class DaapSource : Source, IImportable, IImportSource
+    public class DaapSource : ChildSource, IImportable, IImportSource
     {
+        public delegate void OnLoggedHandler(DaapSource sender);
+        
+        public event OnLoggedHandler LoggedIn;
+        public event OnLoggedHandler LoggedOut;
+        public event OnLoggedHandler Changed;
+        
+        private void OnLoggedIn()
+        {
+        	if (LoggedIn != null)
+        		LoggedIn(this);
+       	}
+       	private void OnLoggedOut()
+       	{
+       		if (LoggedOut != null)
+       			LoggedOut(this);
+       	}
+       	private void OnChanged()
+       	{
+       		if (Changed != null)
+       			Changed(this);
+       	}
+        
         private Service service;
         private Client client;
         private DAAP.Database database;
         private DatabaseProxy database_proxy;
         private bool is_activating;
+        private bool is_logged_in;
         
         public DaapSource(Service service) : base(service.Name, 300)
         {
@@ -55,26 +78,32 @@ namespace Banshee.Plugins.Daap
         
         public override void Activate()
         {
-            if(client == null && !is_activating) {
-                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 {
-                            ThreadAssist.ProxyToMain(PromptLogin);
-                        }
-                    } catch(Exception e) {
+        	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 if (!silent) {
+                       ThreadAssist.ProxyToMain(PromptLogin);
+                   }
+               } catch(Exception e) {
+                   if (!silent)
                         LogCore.Instance.PushError(Catalog.GetString("Cannot login to DAAP share"),
                             e.Message);
-                    }
-                    
-                    is_activating = false;
-                });
-            }
+               }
+               
+               is_activating = false;
+           });
         }
 
         private void AddPlaylistSources ()
@@ -123,10 +152,12 @@ namespace Banshee.Plugins.Daap
 
         internal bool Disconnect (bool logout)
         {
+            OnLoggedOut();
             if(client != null) {
                 if (logout)
                     client.Logout();
-                
+                    
+                is_logged_in = false;
                 client.Dispose();
                 client = null;
                 database = null;
@@ -171,6 +202,11 @@ namespace Banshee.Plugins.Daap
             Name = client.Name;
             
             ThreadAssist.ProxyToMain(delegate {
+                if (!is_logged_in)
+                	OnLoggedIn();
+                else
+                	OnChanged();
+                is_logged_in = true;
                 OnUpdated();
             });
         }
@@ -195,6 +231,10 @@ namespace Banshee.Plugins.Daap
         
         public override int Count {
             get { return database == null ? -1 : database.TrackCount; }
+        }
+        
+        public bool IsLoggedIn {
+        	get { return is_logged_in; }
         }
         
         private static Gdk.Pixbuf icon = IconThemeUtils.LoadIcon(22, "network-server", Gtk.Stock.Network); 
Index: src/Banshee.Plugins/Daap/Makefile.am
===================================================================
RCS file: /cvs/gnome/banshee/src/Banshee.Plugins/Daap/Makefile.am,v
retrieving revision 1.12
diff -u -p -r1.12 Makefile.am
--- src/Banshee.Plugins/Daap/Makefile.am	19 Oct 2006 21:35:37 -0000	1.12
+++ src/Banshee.Plugins/Daap/Makefile.am	19 Oct 2006 23:57:26 -0000
@@ -12,6 +12,7 @@ ASSEMBLY_SOURCES = \
 	$(srcdir)/DaapPlugin.cs \
 	$(srcdir)/DaapCore.cs \
 	$(srcdir)/DaapSource.cs \
+	$(srcdir)/DaapAllSource.cs \
 	$(srcdir)/DaapTrackInfo.cs \
 	$(srcdir)/DaapLoginDialog.cs \
 	$(srcdir)/DatabaseProxy.cs \
