[banshee] Dap/Mtp: Remove unmount, add claim (bgo#731916)
- From: Andrés Aragoneses <aaragoneses src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [banshee] Dap/Mtp: Remove unmount, add claim (bgo#731916)
- Date: Fri, 1 Aug 2014 22:06:07 +0000 (UTC)
commit c0cb25366487914a556ced34117f4db173af9a5f
Author: Nicholas Little <arealityfarbetween googlemail com>
Date: Sat Jul 5 12:01:53 2014 +0100
Dap/Mtp: Remove unmount, add claim (bgo#731916)
We need to unmount MTP devices for banshee to make use of them, this
causes nautilus to produce error messages in some cases, as described in
[1].
This patch adds a parameter to DapSource.DeviceInitialize to signal
whether we should attempt to force the connection to the device (at the
user's request via the ClaimDapAction) or just make a best attempt.
To facilitate this, DapSource subclasses can now throw
InvalidDeviceStateException which will allow them to make a claim on a
device even though they couldn't initialize it. At that point, a new
type, PotentialSource is mapped, enabling the ClaimDapAction.
[1] https://bugzilla.gnome.org/show_bug.cgi?id=731916
.../Banshee.Dap.AppleDevice/AppleDeviceSource.cs | 4 +-
.../Banshee.Dap.Karma/KarmaSource.cs | 4 +-
.../Banshee.Dap.MassStorage/MassStorageSource.cs | 4 +-
.../Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs | 30 ++--
src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs | 15 ++
src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs | 2 +-
.../Banshee.Dap.Gui/InactiveDapContent.cs | 120 ++++++++++++
src/Dap/Banshee.Dap/Banshee.Dap.csproj | 2 +
src/Dap/Banshee.Dap/Banshee.Dap/DapService.cs | 76 ++++++--
src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs | 9 +-
.../Banshee.Dap/InvalidDeviceException.cs | 4 +
src/Dap/Banshee.Dap/Banshee.Dap/PotentialSource.cs | 195 ++++++++++++++++++++
src/Dap/Banshee.Dap/Makefile.am | 2 +
src/Dap/Banshee.Dap/Resources/ActiveSourceUI.xml | 1 +
src/Dap/Banshee.Dap/Resources/GlobalUI.xml | 1 +
15 files changed, 428 insertions(+), 41 deletions(-)
---
diff --git a/src/Dap/Banshee.Dap.AppleDevice/Banshee.Dap.AppleDevice/AppleDeviceSource.cs
b/src/Dap/Banshee.Dap.AppleDevice/Banshee.Dap.AppleDevice/AppleDeviceSource.cs
index 5803ea2..a711640 100644
--- a/src/Dap/Banshee.Dap.AppleDevice/Banshee.Dap.AppleDevice/AppleDeviceSource.cs
+++ b/src/Dap/Banshee.Dap.AppleDevice/Banshee.Dap.AppleDevice/AppleDeviceSource.cs
@@ -70,7 +70,7 @@ namespace Banshee.Dap.AppleDevice
#region Device Setup/Dispose
- public override void DeviceInitialize (IDevice device)
+ public override void DeviceInitialize (IDevice device, bool force)
{
Volume = device as IVolume;
@@ -94,7 +94,7 @@ namespace Banshee.Dap.AppleDevice
throw new InvalidDeviceException ();
}
- base.DeviceInitialize (device);
+ base.DeviceInitialize (device, force);
Name = Volume.Name;
SupportsPlaylists = true;
diff --git a/src/Dap/Banshee.Dap.Karma/Banshee.Dap.Karma/KarmaSource.cs
b/src/Dap/Banshee.Dap.Karma/Banshee.Dap.Karma/KarmaSource.cs
index 4a0a358..d1d3f6f 100644
--- a/src/Dap/Banshee.Dap.Karma/Banshee.Dap.Karma/KarmaSource.cs
+++ b/src/Dap/Banshee.Dap.Karma/Banshee.Dap.Karma/KarmaSource.cs
@@ -50,9 +50,9 @@ namespace Banshee.Dap.Karma
private Dictionary<long, KarmaTrackInfo> track_map =
new Dictionary<long, KarmaTrackInfo>();
- public override void DeviceInitialize(IDevice dev)
+ public override void DeviceInitialize(IDevice dev, bool force)
{
- base.DeviceInitialize(dev);
+ base.DeviceInitialize(dev, force);
if (!IsKarma(dev))
throw new InvalidDeviceException();
diff --git a/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
b/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
index f49a8cf..cdf6d38 100644
--- a/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
+++ b/src/Dap/Banshee.Dap.MassStorage/Banshee.Dap.MassStorage/MassStorageSource.cs
@@ -58,9 +58,9 @@ namespace Banshee.Dap.MassStorage
private IVolume volume;
private IUsbDevice usb_device;
- public override void DeviceInitialize (IDevice device)
+ public override void DeviceInitialize (IDevice device, bool force)
{
- base.DeviceInitialize (device);
+ base.DeviceInitialize (device, force);
volume = device as IVolume;
diff --git a/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
b/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
index bf3eb6a..993223a 100644
--- a/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
+++ b/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
@@ -64,9 +64,9 @@ namespace Banshee.Dap.Mtp
private bool can_sync_albumart = NeverSyncAlbumArtSchema.Get () == false;
private int thumb_width = AlbumArtWidthSchema.Get ();
- public override void DeviceInitialize (IDevice device)
+ public override void DeviceInitialize (IDevice device, bool force)
{
- base.DeviceInitialize (device);
+ base.DeviceInitialize (device, force);
var portInfo = device.ResolveUsbPortInfo ();
if (portInfo == null || portInfo.DeviceNumber == 0) {
@@ -98,19 +98,20 @@ namespace Banshee.Dap.Mtp
//if (v.BusNumber == busnum && v.DeviceNumber == devnum) {
if (v.DeviceNumber == devnum) {
// If gvfs-gphoto has it mounted, unmount it
- if (volume != null && volume.IsMounted) {
+ if (volume != null && volume.IsMounted && force) {
+ Log.DebugFormat ("MtpSource: attempting to unmount {0}", volume.Name);
volume.Unmount ();
}
- for (int i = 5; i > 0 && mtp_device == null; i--) {
- try {
- mtp_device = MtpDevice.Connect (v);
- } catch (Exception) {}
+ if (volume != null && volume.IsMounted) {
+ throw new InvalidDeviceStateException ();
+ }
- if (mtp_device == null) {
- Log.DebugFormat ("Failed to connect to mtp device. Trying {0} more times...", i
- 1);
- Thread.Sleep (2000);
- }
+ mtp_device = MtpDevice.Connect (v);
+
+ if (mtp_device == null) {
+ Log.DebugFormat ("Failed to connect to mtp device {0}", device.Name);
+ throw new InvalidDeviceStateException ();
}
}
}
@@ -465,16 +466,9 @@ namespace Banshee.Dap.Mtp
}
}
- ServiceManager.SourceManager.RemoveSource (this);
mtp_device = null;
}
- protected override void Eject ()
- {
- base.Eject ();
- Dispose ();
- }
-
private static string MakeAlbumKey (string album_artist, string album)
{
return String.Format ("{0}_{1}", album_artist, album);
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs
b/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs
index 949007c..f7aaac5 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapActions.cs
@@ -49,6 +49,11 @@ namespace Banshee.Dap.Gui
public DapActions () : base ("dap")
{
AddImportant (
+ new ActionEntry ("ClaimDapAction", null,
+ Catalog.GetString ("Claim"), null,
+ String.Empty, OnClaimDap)
+ );
+ AddImportant (
new ActionEntry ("SyncDapAction", null,
Catalog.GetString ("Sync"), null,
String.Empty, OnSyncDap)
@@ -57,6 +62,7 @@ namespace Banshee.Dap.Gui
AddUiFromFile ("GlobalUI.xml");
this["SyncDapAction"].IconName = Stock.Refresh;
+ this["ClaimDapAction"].IconName = Stock.Connect;
ServiceManager.SourceManager.ActiveSourceChanged += OnActiveSourceChanged;
Actions.SourceActions.Updated += delegate { UpdateActions (); };
OnActiveSourceChanged (null);
@@ -71,6 +77,7 @@ namespace Banshee.Dap.Gui
}
previous_dap = ActiveSource as DapSource;
+ UpdateActions ();
if (previous_dap != null) {
previous_dap.Sync.Updated += OnSyncUpdated;
@@ -87,6 +94,7 @@ namespace Banshee.Dap.Gui
DapSource dap = Dap;
if (dap != null) {
UpdateAction ("SyncDapAction", dap.Sync.Enabled);
+ UpdateAction ("ClaimDapAction", dap is PotentialSource);
}
}
@@ -98,5 +106,12 @@ namespace Banshee.Dap.Gui
}
}
+ private void OnClaimDap (object o, EventArgs args)
+ {
+ var dap = Dap as PotentialSource;
+ if (dap != null) {
+ dap.TryClaim ();
+ }
+ }
}
}
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs
b/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs
index 81c5349..9ab9f87 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap.Gui/DapContent.cs
@@ -139,7 +139,7 @@ namespace Banshee.Dap.Gui
opts.Dispose ();
}
- private void BuildActions ()
+ internal static void BuildActions()
{
if (actions == null) {
actions = new DapActions ();
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap.Gui/InactiveDapContent.cs
b/src/Dap/Banshee.Dap/Banshee.Dap.Gui/InactiveDapContent.cs
new file mode 100644
index 0000000..c5c9f85
--- /dev/null
+++ b/src/Dap/Banshee.Dap/Banshee.Dap.Gui/InactiveDapContent.cs
@@ -0,0 +1,120 @@
+//
+// InactiveContent.cs
+//
+// Author:
+// Nicholas Little <arealityfarbetween googlemail com>
+//
+// Copyright 2014 Nicholas Little
+//
+// 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.Collections.Generic;
+using System.Linq;
+
+using Gtk;
+
+using Hyena;
+using Hyena.Data;
+using Hyena.Widgets;
+
+using Mono.Unix;
+
+using Banshee.Dap;
+using Banshee.Sources.Gui;
+using Banshee.ServiceStack;
+using Banshee.Preferences;
+using Banshee.Sources;
+using Banshee.Preferences.Gui;
+using Banshee.Widgets;
+
+namespace Banshee.Dap.Gui
+{
+ public class InactiveDapContent : DapPropertiesDisplay
+ {
+ Label title;
+
+ // To avoid the GLib.MissingIntPtrCtorException seen by some; BGO #552169
+ protected InactiveDapContent (IntPtr ptr) : base (ptr)
+ {
+ }
+
+ public InactiveDapContent (DapSource dapSource) : base(dapSource)
+ {
+ dapSource.Properties.PropertyChanged += OnPropertyChanged;
+ BuildWidgets ();
+ }
+
+ private void BuildWidgets ()
+ {
+ var outer = new HBox();
+ var device = new Image (LargeIcon) { Yalign = 0.0f };
+ outer.PackStart (device, false, false, 0);
+
+ var inner = new VBox { Spacing = 5, BorderWidth = 5 };
+ title = new Label { UseMarkup = true, Xalign = 0.0f };
+ SetTitleText (Source.Name);
+ inner.PackStart (title, false, false, 0);
+
+ var box = new HBox { Spacing = 5 };
+ box.PackStart (new Image { IconName = "dialog-warning" }, false, false, 0);
+ box.PackStart (new Label { Markup = ErrorString, UseMarkup = true }, false, false, 0);
+ inner.PackStart (box, false, false, 0);
+
+ outer.PackEnd (inner, false, false, 0);
+ Add (outer);
+ ShowAll ();
+ }
+
+ private void SetTitleText (string name)
+ {
+ title.Markup = String.Format (@"<span size=""x-large"" weight=""bold"">{0}</span>", name);
+ }
+
+ private void OnPropertyChanged (object o, PropertyChangeEventArgs args)
+ {
+ if (args.PropertyName == "Name") {
+ SetTitleText (args.NewValue.ToString ());
+ }
+ }
+
+ protected virtual string ErrorString {
+ get { return DefaultErrorString; }
+ }
+
+ static InactiveDapContent ()
+ {
+ var generic = Catalog.GetString ("Your device appears to be in use by another program");
+ var claimit = String.Format (
+ @"<span weight=""bold"">{0}</span>",
+ Catalog.GetString ("Claim")
+ );
+ var pressit = String.Format (
+ Catalog.GetString ("Press the {0} button above to use it in Banshee"),
+ claimit
+ );
+ DefaultErrorString = string.Format (
+ @"<span size=""large"">{0}." + "\n" + "{1}…</span>", generic, pressit
+ );
+ DapContent.BuildActions ();
+ }
+
+ private static readonly string DefaultErrorString;
+ }
+}
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap.csproj b/src/Dap/Banshee.Dap/Banshee.Dap.csproj
index 465ba8d..2fec82a 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap.csproj
+++ b/src/Dap/Banshee.Dap/Banshee.Dap.csproj
@@ -97,6 +97,8 @@
<Compile Include="Banshee.Dap.Gui\LibrarySyncOptions.cs" />
<Compile Include="Banshee.Dap\DapPriorityNode.cs" />
<Compile Include="Banshee.Dap\SyncPlaylist.cs" />
+ <Compile Include="Banshee.Dap\PotentialSource.cs" />
+ <Compile Include="Banshee.Dap\Gui\InactiveDapContent.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Banshee.Dap.addin.xml">
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap/DapService.cs b/src/Dap/Banshee.Dap/Banshee.Dap/DapService.cs
index c00af21..c3d6c39 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap/DapService.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap/DapService.cs
@@ -29,6 +29,7 @@
//
using System;
+using System.Linq;
using System.Collections.Generic;
using Mono.Unix;
@@ -75,7 +76,6 @@ namespace Banshee.Dap
ServiceManager.HardwareManager.DeviceChanged += OnHardwareDeviceChanged;
ServiceManager.HardwareManager.DeviceRemoved += OnHardwareDeviceRemoved;
ServiceManager.HardwareManager.DeviceCommand += OnDeviceCommand;
- ServiceManager.SourceManager.SourceRemoved += OnSourceRemoved;
initialized = true;
// Now that we've loaded all the enabled DAP providers, load the devices
@@ -133,7 +133,6 @@ namespace Banshee.Dap
ServiceManager.HardwareManager.DeviceAdded -= OnHardwareDeviceAdded;
ServiceManager.HardwareManager.DeviceRemoved -= OnHardwareDeviceRemoved;
ServiceManager.HardwareManager.DeviceCommand -= OnDeviceCommand;
- ServiceManager.SourceManager.SourceRemoved -= OnSourceRemoved;
List<DapSource> dap_sources = new List<DapSource> (sources.Values);
foreach (DapSource source in dap_sources) {
@@ -153,10 +152,17 @@ namespace Banshee.Dap
foreach (TypeExtensionNode node in supported_dap_types) {
try {
DapSource source = (DapSource)node.CreateInstance ();
- source.DeviceInitialize (device);
+ source.DeviceInitialize (device, false);
source.LoadDeviceContents ();
source.AddinId = node.Addin.Id;
return source;
+ } catch (InvalidDeviceStateException) {
+ Log.WarningFormat (
+ "Dap.DapService: invalid state, mapping potential source for {0}",
+ device.Name
+ );
+ DapSource source = new PotentialSource (this, node, device);
+ return source;
} catch (InvalidDeviceException) {
} catch (InvalidCastException e) {
Log.Warning ("Extension is not a DapSource as required", e);
@@ -173,6 +179,25 @@ namespace Banshee.Dap
Scheduler.Schedule (new MapDeviceJob (this, device));
}
+ internal void SwapSource (DapSource oldSource, DapSource newSource, bool makeActive)
+ {
+ if (oldSource.Device.Uuid != newSource.Device.Uuid) {
+ Log.ErrorFormat (
+ "Dap.DapService: swap ignored from {0} to {1}.",
+ oldSource.Device.Uuid, newSource.Device.Uuid
+ );
+ return;
+ }
+ Log.DebugFormat (
+ "Dap.DapService: Swapping {0} with UUID {1} for {2}",
+ oldSource.GetType ().Name, oldSource.Device.Uuid,
+ newSource.GetType ().Name
+ );
+
+ Unmap (oldSource.Device.Uuid);
+ MapSource (newSource, makeActive);
+ }
+
private class MapDeviceJob : IJob
{
IDevice device;
@@ -221,18 +246,28 @@ namespace Banshee.Dap
}
if (source != null) {
- service.MapSource (source);
+ service.MapSource (source, false);
}
}
}
- private void MapSource (DapSource source)
+ private void MapSource (DapSource source, bool active)
{
- ThreadAssist.ProxyToMain (() => {
+ lock (sync) {
+ sources [source.Device.Uuid] = source;
+ source.RequestUnmap += OnRequestUnmap;
+ }
+ ThreadAssist.ProxyToMain (() => {
+
ServiceManager.SourceManager.AddSource (source);
source.NotifyUser ();
+ if (active)
+ {
+ ServiceManager.SourceManager.SetActiveSource (source);
+ }
+
// If there are any queued device commands, see if they are to be
// handled by this new DAP (e.g. --device-activate=file:///media/disk)
try {
@@ -254,6 +289,15 @@ namespace Banshee.Dap
});
}
+ private void OnRequestUnmap (object sender, EventArgs e)
+ {
+ DapSource source = sender as DapSource;
+ if (source != null) {
+ Log.DebugFormat ("DapService: unmap request from {0}", source.Device.Uuid);
+ UnmapDevice (source.Device.Uuid);
+ }
+ }
+
internal void UnmapDevice (string uuid)
{
ThreadAssist.SpawnFromMain (() => Unmap (uuid));
@@ -276,6 +320,7 @@ namespace Banshee.Dap
}
if (source != null) {
+ source.RequestUnmap -= OnRequestUnmap;
source.Dispose ();
ThreadAssist.ProxyToMain (delegate {
try {
@@ -287,14 +332,6 @@ namespace Banshee.Dap
}
}
- private void OnSourceRemoved (SourceEventArgs args)
- {
- DapSource dap_source = args.Source as DapSource;
- if (dap_source != null) {
- UnmapDevice (dap_source.Device.Uuid);
- }
- }
-
private void OnHardwareDeviceAdded (object o, DeviceAddedArgs args)
{
MapDevice (args.Device);
@@ -302,7 +339,16 @@ namespace Banshee.Dap
private void OnHardwareDeviceChanged (object o, DeviceChangedEventArgs args)
{
- MapDevice (args.Device);
+ DapSource source;
+ if (!sources.TryGetValue (args.Device.Uuid, out source)) {
+ MapDevice (args.Device);
+ return;
+ }
+
+ PotentialSource potential = source as PotentialSource;
+ if (potential != null) {
+ potential.TryInitialize ();
+ }
}
private void OnHardwareDeviceRemoved (object o, DeviceRemovedArgs args)
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs b/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
index e4b7983..e4ae1a6 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap/DapSource.cs
@@ -88,7 +88,7 @@ namespace Banshee.Dap
{
}
- public virtual void DeviceInitialize (IDevice device)
+ public virtual void DeviceInitialize (IDevice device, bool force)
{
this.device = device;
TypeUniqueId = device.Serial;
@@ -176,6 +176,8 @@ namespace Banshee.Dap
protected set { supports_podcasts = value; }
}
+ internal event EventHandler RequestUnmap;
+
#region Source
protected override void Initialize ()
@@ -343,6 +345,11 @@ namespace Banshee.Dap
protected override void Eject ()
{
Flush ();
+
+ var h = RequestUnmap;
+ if (h != null) {
+ h (this, EventArgs.Empty);
+ }
}
private void Flush ()
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap/InvalidDeviceException.cs
b/src/Dap/Banshee.Dap/Banshee.Dap/InvalidDeviceException.cs
index f8dbb76..d8f7b66 100644
--- a/src/Dap/Banshee.Dap/Banshee.Dap/InvalidDeviceException.cs
+++ b/src/Dap/Banshee.Dap/Banshee.Dap/InvalidDeviceException.cs
@@ -33,4 +33,8 @@ namespace Banshee.Dap
public class InvalidDeviceException : ApplicationException
{
}
+
+ public class InvalidDeviceStateException : InvalidDeviceException
+ {
+ }
}
diff --git a/src/Dap/Banshee.Dap/Banshee.Dap/PotentialSource.cs
b/src/Dap/Banshee.Dap/Banshee.Dap/PotentialSource.cs
new file mode 100644
index 0000000..8aab60c
--- /dev/null
+++ b/src/Dap/Banshee.Dap/Banshee.Dap/PotentialSource.cs
@@ -0,0 +1,195 @@
+//
+// PotentialSource.cs
+//
+// Author:
+// Nicholas Little <arealityfarbetween googlemail com>
+//
+// Copyright (C) 2014 Nicholas Little
+//
+// 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 Banshee.Collection.Database;
+using Banshee.Dap.Gui;
+using Banshee.Hardware;
+using Banshee.Sources;
+using Banshee.Sources.Gui;
+using Hyena;
+using Mono.Addins;
+
+namespace Banshee.Dap
+{
+ internal class PotentialSource : DapSource
+ {
+ private readonly TypeExtensionNode Claimant;
+ private readonly DapService Service;
+
+ private object lock_object = new object();
+ private bool initialized;
+
+ internal PotentialSource (DapService service, TypeExtensionNode claimant, IDevice device)
+ {
+ Claimant = claimant;
+ Service = service;
+
+ IsTemporary = true;
+
+ SupportsPlaylists = false;
+ SupportsPodcasts = false;
+ SupportsVideo = false;
+
+ DeviceInitialize (device, false);
+ Initialize ();
+ }
+
+ #region overridden members of Source
+
+ protected override void Initialize ()
+ {
+ base.Initialize ();
+ ThreadAssist.ProxyToMain (() => {
+ ClearChildSources ();
+ Properties.Set<ISourceContents> ("Nereid.SourceContents", new InactiveDapContent (this));
+ });
+ }
+
+ #endregion
+
+ #region implemented abstract members of RemovableSource
+
+ public override void Import ()
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override bool CanUnmap {
+ get { return false; }
+ }
+
+ public override bool CanImport {
+ get { return false; }
+ }
+
+ public override bool IsReadOnly {
+ get { return true; }
+ }
+
+ public override long BytesUsed {
+ get { return 0L; }
+ }
+
+ public override long BytesCapacity {
+ get { return 0L; }
+ }
+
+ #endregion
+
+ #region implemented abstract members of DapSource
+
+ public override void AddChildSource (Source child)
+ {
+ }
+
+ public override void RemoveChildSource (Source child)
+ {
+ }
+
+ protected override void AddTrackToDevice (DatabaseTrackInfo track, SafeUri fromUri)
+ {
+ throw new NotSupportedException ();
+ }
+
+ private bool TryDeviceInitialize (bool force, out DapSource source)
+ {
+ lock (lock_object) {
+ source = default (DapSource);
+
+ if (initialized) {
+ return false;
+ }
+
+ SetStatus (
+ AddinManager.CurrentLocalizer.GetString ("Trying to Claim Your Device\u2026"),
+ false,
+ true,
+ "dialog-information"
+ );
+
+ Log.Debug ("PotentialSource: Creating Instance");
+ DapSource src = null;
+ try {
+ src = (DapSource) Claimant.CreateInstance ();
+ Log.Debug ("PotentialSource: Initializing Device");
+ src.DeviceInitialize (Device, force);
+ Log.Debug ("PotentialSource: Loading Contents");
+ src.LoadDeviceContents ();
+
+ Log.DebugFormat ("PotentialSource: Success, new Source {0}", src.Name);
+ src.AddinId = Claimant.Addin.Id;
+ source = src;
+ initialized = true;
+ } catch (InvalidDeviceStateException e) {
+ Log.Warning (e);
+ } catch (InvalidDeviceException e) {
+ Log.Warning (e);
+ } catch (Exception e) {
+ Log.Error (e);
+ }
+
+ bool success = !object.ReferenceEquals (source, default (DapSource));
+
+ SetStatus (
+ success ? AddinManager.CurrentLocalizer.GetString ("Connection Successful. Please
wait\u2026")
+ : AddinManager.CurrentLocalizer.GetString ("Connection Failed\u2026"),
+ !success,
+ success,
+ success ? "dialog-information"
+ : "dialog-warning"
+ );
+
+ return success;
+ }
+ }
+ #endregion
+
+ internal void TryClaim ()
+ {
+ Log.DebugFormat ("PotentialSource: TryClaim {0} as {1}", Device.Name, Claimant.Type);
+ ThreadAssist.SpawnFromMain (() => {
+ DapSource source;
+ if (TryDeviceInitialize (true, out source)) {
+ Service.SwapSource (this, source, true);
+ }
+ });
+ }
+
+ internal void TryInitialize ()
+ {
+ Log.DebugFormat ("PotentialSource: TryInitialize {0} as {1}", Device.Name, Claimant.Type);
+ ThreadAssist.SpawnFromMain (() => {
+ DapSource source;
+ if (TryDeviceInitialize (false, out source)) {
+ Service.SwapSource (this, source, false);
+ }
+ });
+ }
+ }
+}
+
diff --git a/src/Dap/Banshee.Dap/Makefile.am b/src/Dap/Banshee.Dap/Makefile.am
index 11b9038..da8f34f 100644
--- a/src/Dap/Banshee.Dap/Makefile.am
+++ b/src/Dap/Banshee.Dap/Makefile.am
@@ -9,6 +9,7 @@ SOURCES = \
Banshee.Dap.Gui/DapInfoBar.cs \
Banshee.Dap.Gui/DapPropertiesDialog.cs \
Banshee.Dap.Gui/DapPropertiesDisplay.cs \
+ Banshee.Dap.Gui/InactiveDapContent.cs \
Banshee.Dap.Gui/LibrarySyncOptions.cs \
Banshee.Dap.Gui/PurchasedMusicActions.cs \
Banshee.Dap/DapLibrarySync.cs \
@@ -21,6 +22,7 @@ SOURCES = \
Banshee.Dap/MediaGroupSource.cs \
Banshee.Dap/MusicGroupSource.cs \
Banshee.Dap/PodcastGroupSource.cs \
+ Banshee.Dap/PotentialSource.cs \
Banshee.Dap/RemovableSource.cs \
Banshee.Dap/SyncPlaylist.cs \
Banshee.Dap/VideoGroupSource.cs
diff --git a/src/Dap/Banshee.Dap/Resources/ActiveSourceUI.xml
b/src/Dap/Banshee.Dap/Resources/ActiveSourceUI.xml
index eb5bfac..ce56a0c 100644
--- a/src/Dap/Banshee.Dap/Resources/ActiveSourceUI.xml
+++ b/src/Dap/Banshee.Dap/Resources/ActiveSourceUI.xml
@@ -1,6 +1,7 @@
<ui>
<toolbar name="HeaderToolbar">
<placeholder name="SourceActions">
+ <toolitem action="ClaimDapAction"/>
<toolitem action="UnmapSourceAction"/>
<toolitem action="SyncDapAction"/>
</placeholder>
diff --git a/src/Dap/Banshee.Dap/Resources/GlobalUI.xml b/src/Dap/Banshee.Dap/Resources/GlobalUI.xml
index 9f6869c..5287014 100644
--- a/src/Dap/Banshee.Dap/Resources/GlobalUI.xml
+++ b/src/Dap/Banshee.Dap/Resources/GlobalUI.xml
@@ -1,6 +1,7 @@
<ui>
<popup name="RemovableSourceContextMenu" action="RemovableSourceContextMenuAction">
<placeholder name="AboveImportSource">
+ <menuitem action="ClaimDapAction"/>
<menuitem action="SyncDapAction"/>
</placeholder>
</popup>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]