mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-08-30 05:47:38 +00:00
Added support for saving and restoring the sensor history for the last 24h. The sensor history is now saved in a reduced format (duplicate values are removed, gaps are marked with a NAN sensor value.
This commit is contained in:
parent
357498a063
commit
330e93ea64
235
Collections/RingCollection.cs
Normal file
235
Collections/RingCollection.cs
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
|
||||
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License Version
|
||||
1.1 (the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis,
|
||||
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
for the specific language governing rights and limitations under the License.
|
||||
|
||||
The Original Code is the Open Hardware Monitor code.
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael Möller <m.moeller@gmx.ch>.
|
||||
Portions created by the Initial Developer are Copyright (C) 2011
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
use your version of this file under the terms of the MPL, indicate your
|
||||
decision by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the MPL, the GPL or the LGPL.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace OpenHardwareMonitor.Collections {
|
||||
public class RingCollection<T> : IEnumerable<T> {
|
||||
|
||||
private T[] array;
|
||||
|
||||
// first item of collection
|
||||
private int head;
|
||||
|
||||
// index after the last item of the collection
|
||||
private int tail;
|
||||
|
||||
// number of items in the collection
|
||||
private int size;
|
||||
|
||||
public RingCollection() : this(0) { }
|
||||
|
||||
public RingCollection(int capacity) {
|
||||
if (capacity < 0)
|
||||
throw new ArgumentOutOfRangeException("capacity");
|
||||
this.array = new T[capacity];
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
public int Capacity {
|
||||
get {
|
||||
return array.Length;
|
||||
}
|
||||
set {
|
||||
T[] newArray = new T[value];
|
||||
if (size > 0) {
|
||||
if (head < tail) {
|
||||
Array.Copy(array, head, newArray, 0, size);
|
||||
} else {
|
||||
Array.Copy(array, head, newArray, 0, array.Length - head);
|
||||
Array.Copy(array, 0, newArray, array.Length - head, tail);
|
||||
}
|
||||
}
|
||||
this.array = newArray;
|
||||
this.head = 0;
|
||||
this.tail = size == value ? 0 : size;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
|
||||
// remove potential references
|
||||
if (head < tail) {
|
||||
Array.Clear(array, head, size);
|
||||
} else {
|
||||
Array.Clear(array, 0, tail);
|
||||
Array.Clear(array, head, array.Length - head);
|
||||
}
|
||||
|
||||
this.head = 0;
|
||||
this.tail = 0;
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
public void Append(T item) {
|
||||
if (size == array.Length) {
|
||||
int newCapacity = array.Length * 3 / 2;
|
||||
if (newCapacity < array.Length + 8)
|
||||
newCapacity = array.Length + 8;
|
||||
Capacity = newCapacity;
|
||||
}
|
||||
|
||||
array[tail] = item;
|
||||
tail = tail + 1 == array.Length ? 0 : tail + 1;
|
||||
size++;
|
||||
}
|
||||
|
||||
public T Remove() {
|
||||
if (size == 0)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
T result = array[head];
|
||||
array[head] = default(T);
|
||||
head = head + 1 == array.Length ? 0 : head + 1;
|
||||
size--;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public int Count {
|
||||
get {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
public T this[int index] {
|
||||
get {
|
||||
if (index < 0 || index >= size)
|
||||
throw new IndexOutOfRangeException();
|
||||
int i = head + index;
|
||||
if (i >= array.Length)
|
||||
i -= array.Length;
|
||||
return array[i];
|
||||
}
|
||||
set {
|
||||
if (index < 0 || index >= size)
|
||||
throw new IndexOutOfRangeException();
|
||||
int i = head + index;
|
||||
if (i >= array.Length)
|
||||
i -= array.Length;
|
||||
array[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public T First {
|
||||
get {
|
||||
if (size == 0)
|
||||
throw new InvalidOperationException();
|
||||
return array[head];
|
||||
}
|
||||
set {
|
||||
if (size == 0)
|
||||
throw new InvalidOperationException();
|
||||
array[head] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public T Last {
|
||||
get {
|
||||
if (size == 0)
|
||||
throw new InvalidOperationException();
|
||||
return array[tail == 0 ? array.Length - 1 : tail - 1];
|
||||
}
|
||||
set {
|
||||
if (size == 0)
|
||||
throw new InvalidOperationException();
|
||||
array[tail == 0 ? array.Length - 1 : tail - 1] = value;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() {
|
||||
return new RingCollection<T>.Enumerator(this);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() {
|
||||
return new RingCollection<T>.Enumerator(this);
|
||||
}
|
||||
|
||||
private struct Enumerator : IEnumerator<T>, IEnumerator {
|
||||
|
||||
private RingCollection<T> collection;
|
||||
private int index;
|
||||
|
||||
public Enumerator(RingCollection<T> collection) {
|
||||
this.collection = collection;
|
||||
this.index = -1;
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
this.index = -2;
|
||||
}
|
||||
|
||||
public void Reset() {
|
||||
this.index = -1;
|
||||
}
|
||||
|
||||
public T Current {
|
||||
get {
|
||||
if (index < 0)
|
||||
throw new InvalidOperationException();
|
||||
return collection[index];
|
||||
}
|
||||
}
|
||||
|
||||
object IEnumerator.Current {
|
||||
get {
|
||||
if (index < 0)
|
||||
throw new InvalidOperationException();
|
||||
return collection[index];
|
||||
}
|
||||
}
|
||||
|
||||
public bool MoveNext() {
|
||||
if (index == -2)
|
||||
return false;
|
||||
|
||||
index++;
|
||||
|
||||
if (index == collection.size) {
|
||||
index = -2;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -501,12 +501,11 @@ namespace OpenHardwareMonitor.GUI {
|
||||
}
|
||||
|
||||
private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
|
||||
Visible = false;
|
||||
SaveConfiguration();
|
||||
|
||||
Visible = false;
|
||||
systemTray.IsMainIconEnabled = false;
|
||||
timer.Enabled = false;
|
||||
computer.Close();
|
||||
SaveConfiguration();
|
||||
systemTray.Dispose();
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael Möller <m.moeller@gmx.ch>.
|
||||
Portions created by the Initial Developer are Copyright (C) 2009-2010
|
||||
Portions created by the Initial Developer are Copyright (C) 2009-2011
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
@ -88,10 +88,12 @@ namespace OpenHardwareMonitor.GUI {
|
||||
foreach (ISensor sensor in temperatures) {
|
||||
IEnumerable<SensorValue> values = sensor.Values;
|
||||
foreach (SensorValue value in values) {
|
||||
if (!minTempNullable.HasValue || minTempNullable > value.Value)
|
||||
minTempNullable = value.Value;
|
||||
if (!maxTempNullable.HasValue || maxTempNullable < value.Value)
|
||||
maxTempNullable = value.Value;
|
||||
if (!float.IsNaN(value.Value)) {
|
||||
if (!minTempNullable.HasValue || minTempNullable > value.Value)
|
||||
minTempNullable = value.Value;
|
||||
if (!maxTempNullable.HasValue || maxTempNullable < value.Value)
|
||||
maxTempNullable = value.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!minTempNullable.HasValue) {
|
||||
@ -140,6 +142,10 @@ namespace OpenHardwareMonitor.GUI {
|
||||
deltaTime += 2;
|
||||
while (deltaTime + 5 < maxTime && deltaTime < 100)
|
||||
deltaTime += 5;
|
||||
while (deltaTime + 50 < maxTime && deltaTime < 1000)
|
||||
deltaTime += 50;
|
||||
while (deltaTime + 100 < maxTime && deltaTime < 10000)
|
||||
deltaTime += 100;
|
||||
|
||||
List<float> grid = new List<float>(countTime + 1);
|
||||
for (int i = 0; i <= countTime; i++) {
|
||||
@ -149,7 +155,6 @@ namespace OpenHardwareMonitor.GUI {
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e) {
|
||||
|
||||
now = DateTime.Now - new TimeSpan(0, 0, 4);
|
||||
|
||||
List<float> timeGrid = GetTimeGrid();
|
||||
@ -196,14 +201,18 @@ namespace OpenHardwareMonitor.GUI {
|
||||
IEnumerable<SensorValue> values = sensor.Values;
|
||||
PointF last = new PointF();
|
||||
bool first = true;
|
||||
foreach (SensorValue value in values) {
|
||||
PointF point = new PointF(
|
||||
x0 + w - w * (float)(now - value.Time).TotalMinutes / deltaTime,
|
||||
y0 + h - h * (value.Value - tempGrid[0]) / deltaTemp);
|
||||
if (!first)
|
||||
g.DrawLine(pen, last, point);
|
||||
last = point;
|
||||
first = false;
|
||||
foreach (SensorValue v in values) {
|
||||
if (!float.IsNaN(v.Value)) {
|
||||
PointF point = new PointF(
|
||||
x0 + w - w * (float)(now - v.Time).TotalMinutes / deltaTime,
|
||||
y0 + h - h * (v.Value - tempGrid[0]) / deltaTemp);
|
||||
if (!first)
|
||||
g.DrawLine(pen, last, point);
|
||||
last = point;
|
||||
first = false;
|
||||
} else {
|
||||
first = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael Möller <m.moeller@gmx.ch>.
|
||||
Portions created by the Initial Developer are Copyright (C) 20011
|
||||
Portions created by the Initial Developer are Copyright (C) 2011
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
|
@ -208,12 +208,13 @@ namespace OpenHardwareMonitor.Hardware.ATI {
|
||||
}
|
||||
}
|
||||
|
||||
public void Close() {
|
||||
public override void Close() {
|
||||
this.fanControl.ControlModeChanged -= ControlModeChanged;
|
||||
this.fanControl.SoftwareControlValueChanged -=
|
||||
SoftwareControlValueChanged;
|
||||
|
||||
RestoreDefaultFanSpeed();
|
||||
base.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -348,10 +348,11 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close() {
|
||||
public override void Close() {
|
||||
if (temperatureStream != null) {
|
||||
temperatureStream.Close();
|
||||
}
|
||||
base.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -333,9 +333,5 @@ namespace OpenHardwareMonitor.Hardware.CPU {
|
||||
totalLoad.Value = cpuLoad.GetTotalLoad();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Close() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,8 +123,9 @@ namespace OpenHardwareMonitor.Hardware.HDD {
|
||||
count++; count %= UPDATE_DIVIDER;
|
||||
}
|
||||
|
||||
public void Close() {
|
||||
public override void Close() {
|
||||
SMART.CloseHandle(handle);
|
||||
base.Close();
|
||||
}
|
||||
|
||||
public override void Traverse(IVisitor visitor) {
|
||||
|
@ -113,6 +113,13 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
|
||||
public abstract void Update();
|
||||
|
||||
public event HardwareEventHandler Closing;
|
||||
|
||||
public virtual void Close() {
|
||||
if (Closing != null)
|
||||
Closing(this);
|
||||
}
|
||||
|
||||
public void Accept(IVisitor visitor) {
|
||||
if (visitor == null)
|
||||
throw new ArgumentNullException("visitor");
|
||||
|
@ -285,10 +285,11 @@ namespace OpenHardwareMonitor.Hardware.Heatmaster {
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
public void Close() {
|
||||
public override void Close() {
|
||||
serialPort.Close();
|
||||
serialPort.Dispose();
|
||||
serialPort = null;
|
||||
base.Close();
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
|
@ -38,7 +38,7 @@
|
||||
namespace OpenHardwareMonitor.Hardware {
|
||||
|
||||
public delegate void SensorEventHandler(ISensor sensor);
|
||||
|
||||
|
||||
public enum HardwareType {
|
||||
Mainboard,
|
||||
SuperIO,
|
||||
|
@ -47,7 +47,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
private readonly ISettings settings;
|
||||
private readonly LPCIO lpcio;
|
||||
private readonly LMSensors lmSensors;
|
||||
private readonly IHardware[] superIOHardware;
|
||||
private readonly Hardware[] superIOHardware;
|
||||
|
||||
public Mainboard(ISettings settings) {
|
||||
this.settings = settings;
|
||||
@ -80,7 +80,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
superIO = lpcio.SuperIO;
|
||||
}
|
||||
|
||||
superIOHardware = new IHardware[superIO.Length];
|
||||
superIOHardware = new Hardware[superIO.Length];
|
||||
for (int i = 0; i < superIO.Length; i++)
|
||||
superIOHardware[i] = new SuperIOHardware(this, superIO[i],
|
||||
smbios.Board != null ? smbios.Board.Manufacturer :
|
||||
@ -132,6 +132,8 @@ namespace OpenHardwareMonitor.Hardware.Mainboard {
|
||||
public void Close() {
|
||||
if (lmSensors != null)
|
||||
lmSensors.Close();
|
||||
foreach (Hardware hardware in superIOHardware)
|
||||
hardware.Close();
|
||||
}
|
||||
|
||||
public IHardware[] SubHardware {
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael Möller <m.moeller@gmx.ch>.
|
||||
Portions created by the Initial Developer are Copyright (C) 2009-2010
|
||||
Portions created by the Initial Developer are Copyright (C) 2009-2011
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
@ -43,7 +43,7 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
|
||||
internal class NvidiaGroup : IGroup {
|
||||
|
||||
private readonly List<IHardware> hardware = new List<IHardware>();
|
||||
private readonly List<Hardware> hardware = new List<Hardware>();
|
||||
private readonly StringBuilder report = new StringBuilder();
|
||||
|
||||
public NvidiaGroup(ISettings settings) {
|
||||
@ -125,6 +125,9 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
return report.ToString();
|
||||
}
|
||||
|
||||
public void Close() { }
|
||||
public void Close() {
|
||||
foreach (Hardware gpu in hardware)
|
||||
gpu.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Michael Möller <m.moeller@gmx.ch>.
|
||||
Portions created by the Initial Developer are Copyright (C) 2009-2010
|
||||
Portions created by the Initial Developer are Copyright (C) 2009-2011
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
@ -38,6 +38,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using OpenHardwareMonitor.Collections;
|
||||
|
||||
namespace OpenHardwareMonitor.Hardware {
|
||||
@ -49,33 +51,31 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
private readonly int index;
|
||||
private readonly bool defaultHidden;
|
||||
private readonly SensorType sensorType;
|
||||
private readonly IHardware hardware;
|
||||
private readonly Hardware hardware;
|
||||
private readonly ReadOnlyArray<IParameter> parameters;
|
||||
private float? currentValue;
|
||||
private float? minValue;
|
||||
private float? maxValue;
|
||||
private readonly Queue<SensorValue> values =
|
||||
new Queue<SensorValue>(MAX_MINUTES * 15);
|
||||
private readonly RingCollection<SensorValue>
|
||||
values = new RingCollection<SensorValue>();
|
||||
private readonly ISettings settings;
|
||||
private IControl control;
|
||||
|
||||
private float sum;
|
||||
private int count;
|
||||
|
||||
private const int MAX_MINUTES = 120;
|
||||
|
||||
public Sensor(string name, int index, SensorType sensorType,
|
||||
IHardware hardware, ISettings settings) :
|
||||
Hardware hardware, ISettings settings) :
|
||||
this(name, index, sensorType, hardware, null, settings) { }
|
||||
|
||||
public Sensor(string name, int index, SensorType sensorType,
|
||||
IHardware hardware, ParameterDescription[] parameterDescriptions,
|
||||
Hardware hardware, ParameterDescription[] parameterDescriptions,
|
||||
ISettings settings) :
|
||||
this(name, index, false, sensorType, hardware,
|
||||
parameterDescriptions, settings) { }
|
||||
|
||||
public Sensor(string name, int index, bool defaultHidden,
|
||||
SensorType sensorType, IHardware hardware,
|
||||
SensorType sensorType, Hardware hardware,
|
||||
ParameterDescription[] parameterDescriptions, ISettings settings)
|
||||
{
|
||||
this.index = index;
|
||||
@ -92,6 +92,59 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
this.defaultName = name;
|
||||
this.name = settings.GetValue(
|
||||
new Identifier(Identifier, "name").ToString(), name);
|
||||
|
||||
GetSensorValuesFromSettings();
|
||||
|
||||
hardware.Closing += delegate(IHardware h) {
|
||||
SetSensorValuesToSettings();
|
||||
};
|
||||
}
|
||||
|
||||
private void SetSensorValuesToSettings() {
|
||||
using (MemoryStream m = new MemoryStream()) {
|
||||
using (GZipStream c = new GZipStream(m, CompressionMode.Compress))
|
||||
using (BinaryWriter writer = new BinaryWriter(c)) {
|
||||
foreach (SensorValue sensorValue in values) {
|
||||
writer.Write(sensorValue.Time.ToBinary());
|
||||
writer.Write(sensorValue.Value);
|
||||
}
|
||||
}
|
||||
settings.SetValue(new Identifier(Identifier, "values").ToString(),
|
||||
Convert.ToBase64String(m.ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
private void GetSensorValuesFromSettings() {
|
||||
string s = settings.GetValue(
|
||||
new Identifier(Identifier, "values").ToString(), null);
|
||||
|
||||
byte[] array = null;
|
||||
try {
|
||||
array = Convert.FromBase64String(s);
|
||||
using (MemoryStream m = new MemoryStream(array))
|
||||
using (GZipStream c = new GZipStream(m, CompressionMode.Decompress))
|
||||
using (BinaryReader reader = new BinaryReader(c)) {
|
||||
try {
|
||||
while (true) {
|
||||
DateTime time = DateTime.FromBinary(reader.ReadInt64());
|
||||
float value = reader.ReadSingle();
|
||||
AppendValue(value, time);
|
||||
}
|
||||
} catch (EndOfStreamException) { }
|
||||
}
|
||||
} catch { }
|
||||
if (values.Count > 0)
|
||||
AppendValue(float.NaN, DateTime.Now);
|
||||
}
|
||||
|
||||
private void AppendValue(float value, DateTime time) {
|
||||
if (values.Count >= 2 && values.Last.Value == value &&
|
||||
values[values.Count - 2].Value == value) {
|
||||
values.Last = new SensorValue(value, time);
|
||||
return;
|
||||
}
|
||||
|
||||
values.Append(new SensorValue(value, time));
|
||||
}
|
||||
|
||||
public IHardware Hardware {
|
||||
@ -140,15 +193,15 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
return currentValue;
|
||||
}
|
||||
set {
|
||||
while (values.Count > 0 &&
|
||||
(DateTime.Now - values.Peek().Time).TotalMinutes > MAX_MINUTES)
|
||||
values.Dequeue();
|
||||
DateTime now = DateTime.Now;
|
||||
while (values.Count > 0 && (now - values.First.Time).TotalDays > 1)
|
||||
values.Remove();
|
||||
|
||||
if (value.HasValue) {
|
||||
sum += value.Value;
|
||||
count++;
|
||||
if (count == 4) {
|
||||
values.Enqueue(new SensorValue(sum / count, DateTime.Now));
|
||||
AppendValue(sum / count, now);
|
||||
sum = 0;
|
||||
count = 0;
|
||||
}
|
||||
|
@ -340,8 +340,9 @@ namespace OpenHardwareMonitor.Hardware.TBalancer {
|
||||
alternativeRequest.BeginInvoke(null, null);
|
||||
}
|
||||
|
||||
public void Close() {
|
||||
public override void Close() {
|
||||
FTD2XX.FT_Close(handle);
|
||||
base.Close();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -56,6 +56,7 @@
|
||||
<Reference Include="System.Management" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Collections\RingCollection.cs" />
|
||||
<Compile Include="Hardware\ATI\ADL.cs" />
|
||||
<Compile Include="Hardware\ATI\ATIGPU.cs" />
|
||||
<Compile Include="Hardware\ATI\ATIGroup.cs" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user