Browse Source

Add Platform Interface for Mounted drives service.

Add Linux-specific implementation of the interface.
pull/2777/head
Jumar Macato 7 years ago
parent
commit
88ca24c4ef
No known key found for this signature in database GPG Key ID: B19884DAC3A5BF3F
  1. 35
      src/Avalonia.Controls/Platform/IMountedDriveInfoProvider.cs
  2. 28
      src/Avalonia.Controls/Platform/MountedDriveInfo.cs
  3. 1
      src/Avalonia.X11/Avalonia.X11.csproj
  4. 157
      src/Avalonia.X11/Dbus/LinuxDriveInfoProvider.cs
  5. 1395
      src/Avalonia.X11/Dbus/UDisks2.cs

35
src/Avalonia.Controls/Platform/IMountedDriveInfoProvider.cs

@ -0,0 +1,35 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using Avalonia.Platform;
namespace Avalonia.Controls.Platform
{
/// <summary>
/// Defines a platform-specific drive mount information provider implementation.
/// </summary>
public interface IMountedDriveInfoProvider
{
/// <summary>
/// Observable list of currently-mounted drives.
/// </summary>
ObservableCollection<MountedDriveInfo> CurrentDrives { get; }
/// <summary>
/// Determines if the service is currently monitoring.
/// </summary>
bool IsMonitoring { get; }
/// <summary>
/// Start the service polling routine.
/// </summary>
void Start();
/// <summary>
/// Stop the service polling routine.
/// </summary>
void Stop();
}
}

28
src/Avalonia.Controls/Platform/MountedDriveInfo.cs

@ -0,0 +1,28 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Controls.Platform
{
/// <summary>
/// Describes a Drive's properties.
/// </summary>
public class MountedDriveInfo : IEquatable<MountedDriveInfo>
{
public string DriveLabel { get; set; }
public string DriveName { get; set; }
public ulong DriveSizeBytes { get; set; }
public string DevicePath { get; set; }
public string MountPath { get; set; }
public bool Equals(MountedDriveInfo other)
{
return this.DriveLabel.Equals(other.DriveLabel) &&
this.DriveName.Equals(other.DriveName) &&
this.DriveSizeBytes.Equals(other.DriveSizeBytes) &&
this.DevicePath.Equals(other.DevicePath) &&
this.MountPath.Equals(other.MountPath);
}
}
}

1
src/Avalonia.X11/Avalonia.X11.csproj

@ -8,6 +8,7 @@
<ItemGroup>
<ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" />
<ProjectReference Include="..\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<PackageReference Include="Tmds.DBus" Version="0.5.0" />
</ItemGroup>
</Project>

157
src/Avalonia.X11/Dbus/LinuxDriveInfoProvider.cs

@ -0,0 +1,157 @@
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Avalonia.Controls.Platform;
using Tmds.DBus;
namespace Avalonia.X11.Dbus
{
public class LinuxMountedDriveInfoProvider : IMountedDriveInfoProvider
{
private IDisposable[] Disposables;
private readonly Connection _sysDbus;
private readonly IObjectManager udisk2Manager;
public LinuxMountedDriveInfoProvider()
{
this._sysDbus = Connection.System;
this.udisk2Manager = _sysDbus.CreateProxy<IObjectManager>("org.freedesktop.UDisks2", "/org/freedesktop/UDisks2");
}
public ObservableCollection<MountedDriveInfo> CurrentDrives { get; } = new ObservableCollection<MountedDriveInfo>();
private bool _isMonitoring;
public bool IsMonitoring => _isMonitoring;
private async void Poll()
{
var newDriveList = new List<MountedDriveInfo>();
var fProcMounts = File.ReadAllLines("/proc/mounts");
var managedObj = await udisk2Manager.GetManagedObjectsAsync();
var res_drives = managedObj.Where(x => x.Key.ToString().Contains("/org/freedesktop/UDisks2/drives/"))
.Select(x => x.Key);
var res_blockdev = managedObj.Where(x => x.Key.ToString().Contains("/org/freedesktop/UDisks2/block_devices/"))
.Select(x => x);
var res_fs = managedObj.Where(x => x.Key.ToString().Contains("system"))
.Select(x => x.Key)
.ToList();
foreach (var block in res_blockdev)
{
var iblock = _sysDbus.CreateProxy<IBlock>("org.freedesktop.UDisks2", block.Key);
var iblockProps = await iblock.GetAllAsync();
var block_drive = await iblock.GetDriveAsync();
if (!res_drives.Contains(block_drive)) continue;
var drive_key = res_drives.Single(x => x == block_drive);
var drives = _sysDbus.CreateProxy<IDrive>("org.freedesktop.UDisks2", drive_key);
var drivesProps = await drives.GetAllAsync();
var devRawBytes = iblockProps.Device.Take(iblockProps.Device.Length - 1).ToArray();
var devPath = System.Text.Encoding.UTF8.GetString(devRawBytes);
var blockLabel = iblockProps.IdLabel;
var blockSize = iblockProps.Size;
var driveName = drivesProps.Id;
// There should be something in udisks2 to
// get this data but I have no idea where.
var mountPoint = fProcMounts.Select(x => x.Split(' '))
.Where(x => x[0] == devPath)
.Select(x => x[1])
.SingleOrDefault();
if (mountPoint is null) continue;
var k = new MountedDriveInfo()
{
DriveLabel = blockLabel,
DriveName = driveName,
DriveSizeBytes = blockSize,
DevicePath = devPath,
MountPath = mountPoint
};
newDriveList.Add(k);
}
UpdateCollection(newDriveList);
}
// https://stackoverflow.com/questions/19558644/update-an-observablecollection-from-another-collection
private void UpdateCollection(IEnumerable<MountedDriveInfo> newCollection)
{
var newCollectionEnumerator = newCollection.GetEnumerator();
var collectionEnumerator = CurrentDrives.GetEnumerator();
var itemsToDelete = new Collection<MountedDriveInfo>();
while (collectionEnumerator.MoveNext())
{
var item = collectionEnumerator.Current;
// Store item to delete (we can't do it while parse collection.
if (!newCollection.Contains(item))
{
itemsToDelete.Add(item);
}
}
// Handle item to delete.
foreach (var itemToDelete in itemsToDelete)
{
CurrentDrives.Remove(itemToDelete);
}
var i = 0;
while (newCollectionEnumerator.MoveNext())
{
var item = newCollectionEnumerator.Current;
// Handle new item.
if (!CurrentDrives.Contains(item))
{
CurrentDrives.Insert(i, item);
}
// Handle existing item, move at the good index.
if (CurrentDrives.Contains(item))
{
int oldIndex = CurrentDrives.IndexOf(item);
CurrentDrives.Move(oldIndex, i);
}
i++;
}
}
public async void Start()
{
Disposables = new[] {
await udisk2Manager.WatchInterfacesAddedAsync(delegate { Poll(); }),
await udisk2Manager.WatchInterfacesRemovedAsync( delegate { Poll(); })
};
Poll();
_isMonitoring = true;
}
public void Stop()
{
foreach (var Disposable in Disposables)
Disposable.Dispose();
CurrentDrives?.Clear();
_isMonitoring = false;
}
}
}

1395
src/Avalonia.X11/Dbus/UDisks2.cs

File diff suppressed because it is too large
Loading…
Cancel
Save