Commit 5a5cb823 authored by Nicholas Little's avatar Nicholas Little Committed by Andrés G. Aragoneses

Hardware: Add DeviceChanged signal for Dap.Mtp (bgo#729438)

To use an MTP device, we must unmount it and release the connection that
Gvfs makes. Prior to this patch, banshee considered two possible device
events, added and removed so unmounts had to be covered by the latter
case, causing MTP devices to be unmapped as they were being configured.

This patch allows the state transition to occur with the assumption that
the device is still physically present and allows devices which don't
present a Mount in their VolumeAddedArgs to be recognised when their
Mounts do become available. This has the added benefit that further down
the line, we can add sources for yet-to-be-configured devices providing
the user with setup or error handling instructions.

As a test: without this patch, a Nexus7 device would not be recognized
by Banshee when connecting it to a laptop running Ubuntu 14.04.
Signed-off-by: default avatarAndrés G. Aragoneses <knocte@gmail.com>
parent 73691ef0
...@@ -41,6 +41,7 @@ namespace Banshee.Hardware.Gio ...@@ -41,6 +41,7 @@ namespace Banshee.Hardware.Gio
{ {
manager = new Manager (); manager = new Manager ();
manager.DeviceAdded += HandleManagerDeviceAdded; manager.DeviceAdded += HandleManagerDeviceAdded;
manager.DeviceChanged += HandleManagerDeviceChanged;
manager.DeviceRemoved += HandleManagerDeviceRemoved; manager.DeviceRemoved += HandleManagerDeviceRemoved;
} }
...@@ -54,6 +55,11 @@ namespace Banshee.Hardware.Gio ...@@ -54,6 +55,11 @@ namespace Banshee.Hardware.Gio
HandleManagerDeviceAdded (args.Device); HandleManagerDeviceAdded (args.Device);
} }
private void HandleManagerDeviceChanged (object o, MountArgs args)
{
HandleManagerDeviceChanged (args.Device);
}
void HandleManagerDeviceRemoved (object o, MountArgs args) void HandleManagerDeviceRemoved (object o, MountArgs args)
{ {
HandleManagerDeviceRemoved (args.Device); HandleManagerDeviceRemoved (args.Device);
...@@ -71,6 +77,14 @@ namespace Banshee.Hardware.Gio ...@@ -71,6 +77,14 @@ namespace Banshee.Hardware.Gio
} }
} }
private void HandleManagerDeviceChanged (IDevice device)
{
var handler = DeviceChanged;
if (null != handler) {
handler (this, new DeviceChangedEventArgs (device));
}
}
private void HandleManagerDeviceRemoved (IDevice device) private void HandleManagerDeviceRemoved (IDevice device)
{ {
if (device == null) { if (device == null) {
...@@ -86,6 +100,7 @@ namespace Banshee.Hardware.Gio ...@@ -86,6 +100,7 @@ namespace Banshee.Hardware.Gio
#region IHardwareManager #region IHardwareManager
public event DeviceAddedHandler DeviceAdded; public event DeviceAddedHandler DeviceAdded;
public event DeviceChangedHandler DeviceChanged;
public event DeviceRemovedHandler DeviceRemoved; public event DeviceRemovedHandler DeviceRemoved;
public IEnumerable<IDevice> GetAllDevices () public IEnumerable<IDevice> GetAllDevices ()
......
...@@ -3,8 +3,10 @@ ...@@ -3,8 +3,10 @@
// //
// Author: // Author:
// Alex Launi <alex.launi@gmail.com> // Alex Launi <alex.launi@gmail.com>
// Nicholas Little <arealityfarbetween@googlemail.com>
// //
// Copyright (c) 2010 Alex Launi // Copyright (c) 2010 Alex Launi
// Copyright (c) 2014 Nicholas Little
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
...@@ -47,6 +49,7 @@ namespace Banshee.Hardware.Gio ...@@ -47,6 +49,7 @@ namespace Banshee.Hardware.Gio
private Dictionary<IntPtr, GUdev.Device> volume_device_map; private Dictionary<IntPtr, GUdev.Device> volume_device_map;
public event EventHandler<MountArgs> DeviceAdded; public event EventHandler<MountArgs> DeviceAdded;
public event EventHandler<MountArgs> DeviceChanged;
public event EventHandler<MountArgs> DeviceRemoved; public event EventHandler<MountArgs> DeviceRemoved;
public Manager () public Manager ()
...@@ -55,6 +58,7 @@ namespace Banshee.Hardware.Gio ...@@ -55,6 +58,7 @@ namespace Banshee.Hardware.Gio
monitor = VolumeMonitor.Default; monitor = VolumeMonitor.Default;
monitor.MountAdded += HandleMonitorMountAdded; monitor.MountAdded += HandleMonitorMountAdded;
monitor.MountRemoved += HandleMonitorMountRemoved; monitor.MountRemoved += HandleMonitorMountRemoved;
monitor.VolumeAdded += HandleMonitorVolumeAdded;
monitor.VolumeRemoved += HandleMonitorVolumeRemoved; monitor.VolumeRemoved += HandleMonitorVolumeRemoved;
volume_device_map= new Dictionary<IntPtr, GUdev.Device> (); volume_device_map= new Dictionary<IntPtr, GUdev.Device> ();
} }
...@@ -82,50 +86,77 @@ namespace Banshee.Hardware.Gio ...@@ -82,50 +86,77 @@ namespace Banshee.Hardware.Gio
void HandleMonitorMountAdded (object o, MountAddedArgs args) void HandleMonitorMountAdded (object o, MountAddedArgs args)
{ {
// Manually get the mount as gio-sharp translates it to the wrong managed object Hyena.Log.Debug ("Gio.Manager: Received MountAdded Signal");
// TODO: check if this workaround is still needed VolumeChanged (args.Mount.Volume);
var mount = GLib.MountAdapter.GetObject ((GLib.Object) args.Args [0]);
if (mount.Volume == null)
return;
var device = GudevDeviceFromGioMount (mount);
if (device == null) {
Hyena.Log.Debug (string.Format ("Tried to mount {0}/{1} with no matching udev device", mount.Volume.Name, mount.Volume.Uuid));
return;
}
volume_device_map [mount.Volume.Handle] = device;
var h = DeviceAdded;
if (h != null) {
var v = CreateRawVolume (mount.Volume);
if (v == null) {
return;
}
h (this, new MountArgs (HardwareManager.Resolve (new Device (v))));
}
} }
void HandleMonitorMountRemoved (object o, MountRemovedArgs args) void HandleMonitorMountRemoved (object o, MountRemovedArgs args)
{ {
// Manually get the mount as gio-sharp translates it to the wrong managed object Hyena.Log.Debug ("Gio.Manager: received MountRemoved Signal");
var mount = GLib.MountAdapter.GetObject ((GLib.Object) args.Args [0]); VolumeChanged (args.Mount.Volume);
if (mount.Volume == null) { }
private void HandleMonitorVolumeAdded (object o, VolumeAddedArgs args)
{
Hyena.Log.Debug ("Gio.Manager: Received VolumeAdded Signal");
var volume = GLib.VolumeAdapter.GetObject ((GLib.Object) args.Args [0]);
if (volume == null) {
Hyena.Log.Error ("Gio.Manager: ignoring VolumeAdded signal with no volume");
return; return;
} }
VolumeRemoved (mount.Volume); VolumeAdded (volume);
} }
void HandleMonitorVolumeRemoved (object o, VolumeRemovedArgs args) void HandleMonitorVolumeRemoved (object o, VolumeRemovedArgs args)
{ {
Hyena.Log.Debug ("Gio.Manager: received VolumeRemoved signal");
var volume = GLib.VolumeAdapter.GetObject ((GLib.Object) args.Args [0]); var volume = GLib.VolumeAdapter.GetObject ((GLib.Object) args.Args [0]);
if (volume == null) { if (volume == null) {
Hyena.Log.Error ("Gio.Manager: ignoring VolumeRemoved signal with no volume");
return; return;
} }
VolumeRemoved (volume); VolumeRemoved (volume);
} }
private void VolumeAdded (GLib.IVolume volume)
{
var device = GudevDeviceFromGioVolume (volume);
if (device == null) {
Hyena.Log.ErrorFormat ("VolumeAdded: {0}/{1} with no matching udev device", volume.Name, volume.Uuid);
return;
}
volume_device_map [volume.Handle] = device;
var h = DeviceAdded;
if (h != null) {
var raw = CreateRawVolume (volume);
if (raw == null) {
return;
}
var dev = new Device (raw);
h (this, new MountArgs (HardwareManager.Resolve (dev)));
}
}
private void VolumeChanged (GLib.IVolume volume)
{
if (volume == null) {
Hyena.Log.Error ("Gio.Manager: ignoring VolumeChanged signal with no volume");
return;
}
var handler = DeviceChanged;
if (handler != null) {
var raw = CreateRawVolume (volume);
if (raw == null) {
return;
}
var device = new Device (raw);
handler (this, new MountArgs (HardwareManager.Resolve (device)));
}
}
void VolumeRemoved (GLib.IVolume volume) void VolumeRemoved (GLib.IVolume volume)
{ {
......
...@@ -42,6 +42,7 @@ namespace Banshee.Hardware ...@@ -42,6 +42,7 @@ namespace Banshee.Hardware
private Dictionary<string, ICustomDeviceProvider> custom_device_providers = new Dictionary<string, ICustomDeviceProvider> (); private Dictionary<string, ICustomDeviceProvider> custom_device_providers = new Dictionary<string, ICustomDeviceProvider> ();
public event DeviceAddedHandler DeviceAdded; public event DeviceAddedHandler DeviceAdded;
public event DeviceChangedHandler DeviceChanged;
public event DeviceRemovedHandler DeviceRemoved; public event DeviceRemovedHandler DeviceRemoved;
public HardwareManager () public HardwareManager ()
...@@ -66,6 +67,7 @@ namespace Banshee.Hardware ...@@ -66,6 +67,7 @@ namespace Banshee.Hardware
} }
manager.DeviceAdded += OnDeviceAdded; manager.DeviceAdded += OnDeviceAdded;
manager.DeviceChanged += OnDeviceChanged;
manager.DeviceRemoved += OnDeviceRemoved; manager.DeviceRemoved += OnDeviceRemoved;
ServiceManager.Get<DBusCommandService> ().ArgumentPushed += OnCommandLineArgument; ServiceManager.Get<DBusCommandService> ().ArgumentPushed += OnCommandLineArgument;
...@@ -78,6 +80,7 @@ namespace Banshee.Hardware ...@@ -78,6 +80,7 @@ namespace Banshee.Hardware
lock (this) { lock (this) {
if (manager != null) { if (manager != null) {
manager.DeviceAdded -= OnDeviceAdded; manager.DeviceAdded -= OnDeviceAdded;
manager.DeviceChanged -= OnDeviceChanged;
manager.DeviceRemoved -= OnDeviceRemoved; manager.DeviceRemoved -= OnDeviceRemoved;
manager.Dispose (); manager.Dispose ();
manager = null; manager = null;
...@@ -186,6 +189,16 @@ namespace Banshee.Hardware ...@@ -186,6 +189,16 @@ namespace Banshee.Hardware
} }
} }
private void OnDeviceChanged (object o, DeviceChangedEventArgs args)
{
lock (this) {
var handler = DeviceChanged;
if (null != handler) {
handler (this, args);
}
}
}
private void OnDeviceRemoved (object o, DeviceRemovedArgs args) private void OnDeviceRemoved (object o, DeviceRemovedArgs args)
{ {
lock (this) { lock (this) {
......
...@@ -34,6 +34,7 @@ namespace Banshee.Hardware ...@@ -34,6 +34,7 @@ namespace Banshee.Hardware
public interface IHardwareManager : IDisposable public interface IHardwareManager : IDisposable
{ {
event DeviceAddedHandler DeviceAdded; event DeviceAddedHandler DeviceAdded;
event DeviceChangedHandler DeviceChanged;
event DeviceRemovedHandler DeviceRemoved; event DeviceRemovedHandler DeviceRemoved;
IEnumerable<IDevice> GetAllDevices (); IEnumerable<IDevice> GetAllDevices ();
...@@ -43,6 +44,7 @@ namespace Banshee.Hardware ...@@ -43,6 +44,7 @@ namespace Banshee.Hardware
} }
public delegate void DeviceAddedHandler (object o, DeviceAddedArgs args); public delegate void DeviceAddedHandler (object o, DeviceAddedArgs args);
public delegate void DeviceChangedHandler (object o, DeviceChangedEventArgs args);
public delegate void DeviceRemovedHandler (object o, DeviceRemovedArgs args); public delegate void DeviceRemovedHandler (object o, DeviceRemovedArgs args);
public sealed class DeviceAddedArgs : EventArgs public sealed class DeviceAddedArgs : EventArgs
...@@ -59,6 +61,20 @@ namespace Banshee.Hardware ...@@ -59,6 +61,20 @@ namespace Banshee.Hardware
} }
} }
public sealed class DeviceChangedEventArgs : EventArgs
{
private readonly IDevice device;
public DeviceChangedEventArgs (IDevice device)
{
this.device = device;
}
public IDevice Device {
get { return device; }
}
}
public sealed class DeviceRemovedArgs : EventArgs public sealed class DeviceRemovedArgs : EventArgs
{ {
private string device_uuid; private string device_uuid;
......
...@@ -63,8 +63,15 @@ namespace Banshee.Dap.MassStorage ...@@ -63,8 +63,15 @@ namespace Banshee.Dap.MassStorage
base.DeviceInitialize (device); base.DeviceInitialize (device);
volume = device as IVolume; volume = device as IVolume;
if (volume == null || !volume.IsMounted || (usb_device = volume.ResolveRootUsbDevice ()) == null) {
if (volume == null || (usb_device = volume.ResolveRootUsbDevice ()) == null) {
throw new InvalidDeviceException ();
}
if (!volume.IsMounted && !volume.CanMount) {
throw new InvalidDeviceException (); throw new InvalidDeviceException ();
} else if (!volume.IsMounted) {
volume.Mount ();
} }
ms_device = DeviceMapper.Map (this); ms_device = DeviceMapper.Map (this);
......
...@@ -72,6 +72,7 @@ namespace Banshee.Dap ...@@ -72,6 +72,7 @@ namespace Banshee.Dap
AddinManager.AddExtensionNodeHandler ("/Banshee/Dap/DeviceClass", OnExtensionChanged); AddinManager.AddExtensionNodeHandler ("/Banshee/Dap/DeviceClass", OnExtensionChanged);
ServiceManager.HardwareManager.DeviceAdded += OnHardwareDeviceAdded; ServiceManager.HardwareManager.DeviceAdded += OnHardwareDeviceAdded;
ServiceManager.HardwareManager.DeviceChanged += OnHardwareDeviceChanged;
ServiceManager.HardwareManager.DeviceRemoved += OnHardwareDeviceRemoved; ServiceManager.HardwareManager.DeviceRemoved += OnHardwareDeviceRemoved;
ServiceManager.HardwareManager.DeviceCommand += OnDeviceCommand; ServiceManager.HardwareManager.DeviceCommand += OnDeviceCommand;
ServiceManager.SourceManager.SourceRemoved += OnSourceRemoved; ServiceManager.SourceManager.SourceRemoved += OnSourceRemoved;
...@@ -294,6 +295,11 @@ namespace Banshee.Dap ...@@ -294,6 +295,11 @@ namespace Banshee.Dap
MapDevice (args.Device); MapDevice (args.Device);
} }
private void OnHardwareDeviceChanged (object o, DeviceChangedEventArgs args)
{
MapDevice (args.Device);
}
private void OnHardwareDeviceRemoved (object o, DeviceRemovedArgs args) private void OnHardwareDeviceRemoved (object o, DeviceRemovedArgs args)
{ {
UnmapDevice (args.DeviceUuid); UnmapDevice (args.DeviceUuid);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment