[banshee] UPnPService: Handle UPnP device removal



commit db694d89e19c1dd0c39f9937c4bd0f010d4d71ac
Author: Bertrand Lorentz <bertrand lorentz gmail com>
Date:   Sat Mar 10 17:45:06 2012 +0100

    UPnPService: Handle UPnP device removal
    
    When a UPnP device goes away, the corresponding sources are now removed.
    To do this, we keep track of the association between each device UDN
    (which is a UUID) and the corresponding UPnPServerSource.
    
    The "Shared Media" container source is now only displayed if there
    something under it. This is the same behavior as the DAAP container
    source.

 .../Banshee.UPnPClient/UPnPService.cs              |   63 ++++++++++++++++++-
 1 files changed, 59 insertions(+), 4 deletions(-)
---
diff --git a/src/Extensions/Banshee.UPnPClient/Banshee.UPnPClient/UPnPService.cs b/src/Extensions/Banshee.UPnPClient/Banshee.UPnPClient/UPnPService.cs
index 6866811..6fffdd9 100644
--- a/src/Extensions/Banshee.UPnPClient/Banshee.UPnPClient/UPnPService.cs
+++ b/src/Extensions/Banshee.UPnPClient/Banshee.UPnPClient/UPnPService.cs
@@ -49,21 +49,39 @@ namespace Banshee.UPnPClient
         private Mono.Upnp.Client client;
         private UPnPContainerSource container;
 
+        private Dictionary<string, UPnPServerSource> source_map;
+
         void IExtensionService.Initialize ()
         {
+            source_map = new Dictionary<string, UPnPServerSource> ();
             container = new UPnPContainerSource ();
-            ServiceManager.SourceManager.AddSource (container);
 
             client = new Mono.Upnp.Client ();
             client.DeviceAdded += DeviceAdded;
+            client.DeviceRemoved += DeviceRemoved;
 
             client.BrowseAll ();
         }
     
         public void Dispose ()
         {
-            if (container != null)
-            {
+            if (client != null) {
+                client.DeviceAdded -= DeviceAdded;
+                client.DeviceRemoved -= DeviceRemoved;
+                client.Dispose ();
+            }
+
+            if (source_map != null) {
+                foreach (var kv in source_map) {
+                    if (kv.Value != null) {
+                        kv.Value.Disconnect ();
+                    }
+                }
+
+                source_map.Clear ();
+            }
+
+            if (container != null) {
                 foreach (UPnPServerSource source in container.Children) {
                     source.Disconnect ();
                 }
@@ -75,16 +93,53 @@ namespace Banshee.UPnPClient
 
         void DeviceAdded (object sender, DeviceEventArgs e)
         {
-            Log.DebugFormat ("UPnPService.DeviceFound {0} ({1})",e.Device.ToString (), e.Device.Type);
+            Log.DebugFormat ("UPnPService.DeviceAdded ({0}) {1}", e.Device.Type, e.Device.Udn);
             Device device = e.Device.GetDevice ();
 
             if (device.Type.Type == "MediaServer") {
                 Log.DebugFormat ("UPnPService MediaServer Found: {0} {1}", device.ModelName, device.ModelNumber);
                 UPnPServerSource source = new UPnPServerSource (device);
+
+                string key = device.Udn;
+                if (source_map.Count == 0) {
+                    ThreadAssist.ProxyToMain (delegate {
+                        ServiceManager.SourceManager.AddSource (container);
+                    });
+                }
+
+                if (source_map.ContainsKey (key)) {
+                    // Received new connection info for service
+                    container.RemoveChildSource (source_map [key]);
+                    source_map [key] = source;
+                } else {
+                    // New service information
+                    source_map.Add (key, source);
+                }
+
                 container.AddChildSource (source);
             }
         }
 
+        void DeviceRemoved (object sender, DeviceEventArgs e)
+        {
+            Log.DebugFormat ("UPnPService.DeviceRemoved ({0}) {1}", e.Device.Type, e.Device.Udn);
+
+            // We can't use e.Device.GetDevice () here, because the device might already be disposed
+            if (e.Device.Type.Type == "MediaServer") {
+                Log.DebugFormat ("UPnPService MediaServer Removed: {0} {1}", e.Device.Type, e.Device.Udn);
+                String key = e.Device.Udn;
+                UPnPServerSource source = source_map [key];
+
+                source.Disconnect ();
+                container.RemoveChildSource (source);
+                source_map.Remove (key);
+
+                if (source_map.Count == 0) {
+                    ServiceManager.SourceManager.RemoveSource (container);
+                }
+            }
+        }
+
         string IService.ServiceName {
             get { return "uPnP Client service"; }
         }



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