Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add plugin framework [wip] #14

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/dotnet-desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- name: Build InfoPanel
run: |
dotnet restore
dotnet publish InfoPanel\InfoPanel.csproj -c Release -o "${{ github.workspace }}\InfoPanel\bin\publish\win-x64" -r win-x64 --self-contained -p:PublishReadyToRun=true
dotnet publish -p:PublishProfile=FolderProfile

- name: Install and Compile Inno Setup Installer
shell: powershell
Expand Down
7 changes: 0 additions & 7 deletions InfoPanel.Contract/IPanelData.cs

This file was deleted.

22 changes: 0 additions & 22 deletions InfoPanel.Contract/PanelData.cs

This file was deleted.

129 changes: 129 additions & 0 deletions InfoPanel.Extras/DriveInfoPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using InfoPanel.Plugins;

namespace InfoPanel.Extras
{
public class DriveInfoPlugin : BasePlugin
{
public override TimeSpan UpdateInterval => TimeSpan.FromSeconds(1);

public override string? ConfigFilePath => null;

private readonly List<PluginContainer> _containers = [];

public DriveInfoPlugin() : base("drive-info-plugin", "Drive Info", "Retrieves local disk space information.")
{
}

public override void Close()
{
throw new NotImplementedException();
}

public override void Initialize()
{
foreach (DriveInfo drive in DriveInfo.GetDrives())
{
if (drive.IsReady)
{
PluginContainer container = new(drive.Name.TrimEnd('\\'));
container.Entries.Add(new PluginText("name", "Name", drive.Name.TrimEnd('\\')));
container.Entries.Add(new PluginText("type", "Type", drive.DriveType.ToString()));
container.Entries.Add(new PluginText("volume_label", "Volume Label", drive.VolumeLabel));
container.Entries.Add(new PluginText("format", "Format", drive.DriveFormat));
container.Entries.Add(new PluginSensor("total_size", "Total Size", drive.TotalSize / 1024 / 1024, "MB"));
container.Entries.Add(new PluginSensor("free_space", "Free Space", drive.TotalFreeSpace / 1024 / 1024, "MB"));
container.Entries.Add(new PluginSensor("available_space", "Available Space", drive.AvailableFreeSpace / 1024 / 1024, "MB"));
container.Entries.Add(new PluginSensor("used_space", "Used Space", (drive.TotalSize - drive.TotalFreeSpace) / 1024 / 1024, "MB"));

_containers.Add(container);
}
}
}

public override void Load(List<IPluginContainer> containers)
{
containers.AddRange(_containers);
}

public override void Update()
{
throw new NotImplementedException();
}

public override Task UpdateAsync(CancellationToken cancellationToken)
{
foreach (var container in _containers)
{
DriveInfo drive = new(container.Name);

if (drive.IsReady)
{
foreach (var entry in container.Entries)
{
switch (entry.Id)
{
case "type":
{
if (entry is PluginText text)
{
text.Value = drive.DriveType.ToString();
}
}
break;
case "volume_label":
{
if (entry is PluginText text)
{
text.Value = drive.VolumeLabel;
}
}
break;
case "format":
{
if (entry is PluginText text)
{
text.Value = drive.DriveFormat;
}
}
break;
case "total_size":
{
if (entry is PluginSensor sensor)
{
sensor.Value = drive.TotalSize / 1024 / 1024;
}
}
break;
case "free_space":
{
if (entry is PluginSensor sensor)
{
sensor.Value = drive.TotalFreeSpace / 1024 / 1024;
}
}
break;
case "available_space":
{
if (entry is PluginSensor sensor)
{
sensor.Value = drive.AvailableFreeSpace / 1024 / 1024;
}
}
break;
case "used_space":
{
if (entry is PluginSensor sensor)
{
sensor.Value = (drive.TotalSize - drive.TotalFreeSpace) / 1024 / 1024;
}
}
break;
}
}
}
}

return Task.CompletedTask;
}
}
}
24 changes: 24 additions & 0 deletions InfoPanel.Extras/InfoPanel.Extras.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableDynamicLoading>true</EnableDynamicLoading>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<Platforms>x64</Platforms>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ini-parser-netstandard" Version="2.5.2" />
<PackageReference Include="NAudio.Wasapi" Version="2.2.1" />
<PackageReference Include="OpenWeatherMap.Standard" Version="3.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\InfoPanel.Plugins\InfoPanel.Plugins.csproj">
<Private>false</Private>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>
</ItemGroup>
</Project>
69 changes: 69 additions & 0 deletions InfoPanel.Extras/IpifyPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using InfoPanel.Plugins;
using System.Diagnostics;

namespace InfoPanel.Extras
{
public class IpifyPlugin : BasePlugin
{
private readonly PluginText _ipv4Sensor = new("IPv4", "-");
private readonly PluginText _ipv6Sensor = new("IPv6", "-");
private readonly HttpClient _httpClient = new();

public override string? ConfigFilePath => null;
public override TimeSpan UpdateInterval => TimeSpan.FromMinutes(5);

public IpifyPlugin() : base("ipify-plugin", "Public IP - Ipify", "IPv4 & IPv6 lookup via ipify.org API.")
{
}

public override void Initialize()
{
}

public override void Load(List<IPluginContainer> containers)
{
var container = new PluginContainer("Public IP");
container.Entries.Add(_ipv4Sensor);
container.Entries.Add(_ipv6Sensor);
containers.Add(container);
}

public override void Close()
{
_httpClient.Dispose();
}

public override void Update()
{
throw new NotImplementedException();
}

public override async Task UpdateAsync(CancellationToken cancellationToken)
{
await GetIp(cancellationToken);
}

private async Task GetIp(CancellationToken cancellationToken)
{
try
{
var ipv4 = await _httpClient.GetStringAsync("https://api.ipify.org", cancellationToken);
_ipv4Sensor.Value = ipv4;
}
catch
{
Trace.WriteLine("IpifyPlugin: Failed to get IPv6");
}

try
{
var ipv6 = await _httpClient.GetStringAsync("https://api6.ipify.org", cancellationToken);
_ipv6Sensor.Value = ipv6;
}
catch
{
Trace.WriteLine("IpifyPlugin: Failed to get IPv6");
}
}
}
}
127 changes: 127 additions & 0 deletions InfoPanel.Extras/VolumePlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
using InfoPanel.Plugins;
using NAudio.CoreAudioApi;
using System.ComponentModel;

namespace InfoPanel.Extras
{
public class VolumePlugin : BasePlugin
{
private readonly List<PluginContainer> _containers = [];

private MMDeviceEnumerator? _deviceEnumerator;

private readonly Dictionary<string, MMDevice> _deviceCache = [];

public VolumePlugin() : base("volume-plugin","Volume Info", "Retrieves audio output devices and relevant details. Powered by NAudio.")
{
}
public override string? ConfigFilePath => null;
public override TimeSpan UpdateInterval => TimeSpan.FromMilliseconds(50);

public override void Initialize()
{
//add default first
_deviceEnumerator = new();
using var defaultDevice = _deviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);

PluginContainer container = new("Default");
container.Entries.Add(new PluginSensor("volume", "Volume", (float)Math.Round(defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar * 100), "%"));
container.Entries.Add(new PluginText("mute", "Mute", defaultDevice.AudioEndpointVolume.Mute.ToString()));
_containers.Add(container);

var devices = _deviceEnumerator.EnumerateAudioEndPoints(DataFlow.Render, DeviceState.Active);
foreach (var device in devices)
{
container = new(device.ID, device.FriendlyName);
container.Entries.Add(new PluginText("device_friendly_name", "Device Name", device.DeviceFriendlyName));
container.Entries.Add(new PluginText("friendly_name", "Name", device.FriendlyName));
container.Entries.Add(new PluginText("short_name", "Short Name", device.FriendlyName.Replace($"({defaultDevice.DeviceFriendlyName})", "")));
container.Entries.Add(new PluginSensor("volume", "Volume", (float)Math.Round(device.AudioEndpointVolume.MasterVolumeLevelScalar * 100), "%"));
container.Entries.Add(new PluginText("mute", "Mute", device.AudioEndpointVolume.Mute.ToString()));
_containers.Add(container);

_deviceCache.TryAdd(device.ID, device);
}
}

public override void Close()
{
_deviceEnumerator?.Dispose();
foreach (var device in _deviceCache.Values)
{
device.Dispose();
}
_deviceCache.Clear();
}

public override void Load(List<IPluginContainer> containers)
{
containers.AddRange(_containers);
}

public override Task UpdateAsync(CancellationToken cancellationToken)
{
Update();
return Task.CompletedTask;
}

public override void Update()
{
foreach(var container in _containers)
{
MMDevice? device = null;

try
{
if (container.Name == "Default")
{
var tempDevice = _deviceEnumerator?.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
if (tempDevice != null)
{
device = _deviceCache.GetValueOrDefault(tempDevice.ID);

if(device == null)
{
_deviceCache.TryAdd(tempDevice.ID, tempDevice);
device = tempDevice;
} else
{
tempDevice.Dispose();
}
}
}
else
{
device = _deviceCache.GetValueOrDefault(container.Id);
}

if (device != null)
{
foreach (var entry in container.Entries)
{
switch (entry.Id)
{
case "volume":
{
if (entry is PluginSensor sensor)
{
sensor.Value = (float)Math.Round(device.AudioEndpointVolume.MasterVolumeLevelScalar * 100);
}
}
break;
case "mute":
{
if (entry is PluginText text)
{
text.Value = device.AudioEndpointVolume.Mute.ToString();
}
}
break;
}
}
}
}catch { }
}
}
}
}
Loading
Loading