mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
@@ -40,6 +40,7 @@ internal class Popup: NSView {
|
||||
private var chargingStateField: NSTextField? = nil
|
||||
|
||||
private var processes: [ProcessView] = []
|
||||
private var processesInitialized: Bool = false
|
||||
|
||||
public init() {
|
||||
super.init(frame: NSRect(
|
||||
@@ -189,14 +190,18 @@ internal class Popup: NSView {
|
||||
|
||||
public func processCallback(_ list: [TopProcess]) {
|
||||
DispatchQueue.main.async(execute: {
|
||||
for i in 0..<list.count {
|
||||
let process = list[i]
|
||||
let index = list.count-i-1
|
||||
if self.processes.indices.contains(index) {
|
||||
self.processes[index].label = process.name != nil ? process.name! : process.command
|
||||
self.processes[index].value = "\(process.usage)%"
|
||||
self.processes[index].icon = process.icon
|
||||
if (self.window?.isVisible ?? false) || !self.processesInitialized {
|
||||
for i in 0..<list.count {
|
||||
let process = list[i]
|
||||
let index = list.count-i-1
|
||||
if self.processes.indices.contains(index) {
|
||||
self.processes[index].label = process.name != nil ? process.name! : process.command
|
||||
self.processes[index].value = "\(process.usage)%"
|
||||
self.processes[index].icon = process.icon
|
||||
}
|
||||
}
|
||||
|
||||
self.processesInitialized = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ internal class Popup: NSView {
|
||||
private var chart: LineChartView? = nil
|
||||
private var circle: CircleGraphView? = nil
|
||||
private var temperatureCircle: HalfCircleGraphView? = nil
|
||||
private var ready: Bool = false
|
||||
private var initialized: Bool = false
|
||||
private var processesInitialized: Bool = false
|
||||
|
||||
private var processes: [ProcessView] = []
|
||||
|
||||
@@ -151,28 +152,28 @@ internal class Popup: NSView {
|
||||
|
||||
public func loadCallback(_ value: CPU_Load, tempValue: Double?) {
|
||||
DispatchQueue.main.async(execute: {
|
||||
if (self.window?.isVisible ?? false) || !self.ready {
|
||||
if (self.window?.isVisible ?? false) || !self.initialized {
|
||||
self.systemField?.stringValue = "\(Int(value.systemLoad.rounded(toPlaces: 2) * 100)) %"
|
||||
self.userField?.stringValue = "\(Int(value.userLoad.rounded(toPlaces: 2) * 100)) %"
|
||||
self.idleField?.stringValue = "\(Int(value.idleLoad.rounded(toPlaces: 2) * 100)) %"
|
||||
|
||||
let v = Int(value.totalUsage.rounded(toPlaces: 2) * 100)
|
||||
self.loadField?.stringValue = "\(v) %"
|
||||
self.ready = true
|
||||
}
|
||||
|
||||
self.circle?.setValue(value.totalUsage)
|
||||
self.circle?.setSegments([
|
||||
circle_segment(value: value.systemLoad, color: NSColor.systemRed),
|
||||
circle_segment(value: value.userLoad, color: NSColor.systemBlue),
|
||||
])
|
||||
if tempValue != nil {
|
||||
self.temperatureCircle?.setValue(tempValue!)
|
||||
self.initialized = true
|
||||
|
||||
let formatter = MeasurementFormatter()
|
||||
formatter.numberFormatter.maximumFractionDigits = 0
|
||||
let measurement = Measurement(value: tempValue!, unit: UnitTemperature.celsius)
|
||||
self.temperatureCircle?.setText(formatter.string(from: measurement))
|
||||
self.circle?.setValue(value.totalUsage)
|
||||
self.circle?.setSegments([
|
||||
circle_segment(value: value.systemLoad, color: NSColor.systemRed),
|
||||
circle_segment(value: value.userLoad, color: NSColor.systemBlue),
|
||||
])
|
||||
if tempValue != nil {
|
||||
self.temperatureCircle?.setValue(tempValue!)
|
||||
|
||||
let formatter = MeasurementFormatter()
|
||||
formatter.numberFormatter.maximumFractionDigits = 0
|
||||
let measurement = Measurement(value: tempValue!, unit: UnitTemperature.celsius)
|
||||
self.temperatureCircle?.setText(formatter.string(from: measurement))
|
||||
}
|
||||
}
|
||||
self.chart?.addValue(value.totalUsage)
|
||||
})
|
||||
@@ -180,14 +181,18 @@ internal class Popup: NSView {
|
||||
|
||||
public func processCallback(_ list: [TopProcess]) {
|
||||
DispatchQueue.main.async(execute: {
|
||||
for i in 0..<list.count {
|
||||
let process = list[i]
|
||||
let index = list.count-i-1
|
||||
if self.processes.indices.contains(index) {
|
||||
self.processes[index].label = process.name != nil ? process.name! : process.command
|
||||
self.processes[index].value = "\(process.usage)%"
|
||||
self.processes[index].icon = process.icon
|
||||
if (self.window?.isVisible ?? false) || !self.processesInitialized {
|
||||
for i in 0..<list.count {
|
||||
let process = list[i]
|
||||
let index = list.count-i-1
|
||||
if self.processes.indices.contains(index) {
|
||||
self.processes[index].label = process.name != nil ? process.name! : process.command
|
||||
self.processes[index].value = "\(process.usage)%"
|
||||
self.processes[index].icon = process.icon
|
||||
}
|
||||
}
|
||||
|
||||
self.processesInitialized = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ internal class DiskView: NSView {
|
||||
public let name: String
|
||||
public let size: Int64
|
||||
private let uri: URL?
|
||||
private var ready: Bool = false
|
||||
|
||||
private let nameHeight: CGFloat = 20
|
||||
private let legendHeight: CGFloat = 12
|
||||
@@ -196,22 +197,26 @@ internal class DiskView: NSView {
|
||||
|
||||
public func update(free: Int64, read: Int64?, write: Int64?) {
|
||||
DispatchQueue.main.async(execute: {
|
||||
if self.legendField != nil {
|
||||
self.legendField?.stringValue = "Used \(Units(bytes: (self.size - free)).getReadableMemory()) from \(Units(bytes: self.size).getReadableMemory())"
|
||||
self.percentageField?.stringValue = "\(Int8((Double(self.size - free) / Double(self.size)) * 100))%"
|
||||
}
|
||||
|
||||
if self.usedBarSpace != nil {
|
||||
let percentage = CGFloat(self.size - free) / CGFloat(self.size)
|
||||
let width: CGFloat = ((self.mainView.frame.width - 2) * percentage) / 1
|
||||
self.usedBarSpace?.setFrameSize(NSSize(width: width, height: self.usedBarSpace!.frame.height))
|
||||
}
|
||||
|
||||
if read != nil {
|
||||
self.setReadState(read != 0)
|
||||
}
|
||||
if write != nil {
|
||||
self.setWriteState(write != 0)
|
||||
if (self.window?.isVisible ?? false) || !self.ready {
|
||||
if self.legendField != nil {
|
||||
self.legendField?.stringValue = "Used \(Units(bytes: (self.size - free)).getReadableMemory()) from \(Units(bytes: self.size).getReadableMemory())"
|
||||
self.percentageField?.stringValue = "\(Int8((Double(self.size - free) / Double(self.size)) * 100))%"
|
||||
}
|
||||
|
||||
if self.usedBarSpace != nil {
|
||||
let percentage = CGFloat(self.size - free) / CGFloat(self.size)
|
||||
let width: CGFloat = ((self.mainView.frame.width - 2) * percentage) / 1
|
||||
self.usedBarSpace?.setFrameSize(NSSize(width: width, height: self.usedBarSpace!.frame.height))
|
||||
}
|
||||
|
||||
if read != nil {
|
||||
self.setReadState(read != 0)
|
||||
}
|
||||
if write != nil {
|
||||
self.setWriteState(write != 0)
|
||||
}
|
||||
|
||||
self.ready = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -78,13 +78,18 @@ internal class Settings: NSView, Settings_v {
|
||||
}
|
||||
|
||||
private func addDiskSelector() {
|
||||
let view: NSView = NSView(frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin*2 + 30, width: self.frame.width, height: 29))
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
y: Constants.Settings.margin*2 + 30,
|
||||
width: self.frame.width - Constants.Settings.margin*2,
|
||||
height: 30
|
||||
))
|
||||
|
||||
let rowTitle: NSTextField = LabelField(frame: NSRect(x: 0, y: (view.frame.height - 16)/2, width: view.frame.width - 52, height: 17), "Disk to show")
|
||||
rowTitle.font = NSFont.systemFont(ofSize: 13, weight: .light)
|
||||
rowTitle.textColor = .textColor
|
||||
|
||||
self.button = NSPopUpButton(frame: NSRect(x: view.frame.width - 140 - Constants.Settings.margin*2, y: -1, width: 140, height: 30))
|
||||
self.button = NSPopUpButton(frame: NSRect(x: view.frame.width - 140, y: -1, width: 140, height: 30))
|
||||
self.button!.target = self
|
||||
self.button?.action = #selector(self.handleSelection)
|
||||
|
||||
|
||||
24
Modules/GPU/Info.plist
Normal file
24
Modules/GPU/Info.plist
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
60
Modules/GPU/config.plist
Normal file
60
Modules/GPU/config.plist
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Name</key>
|
||||
<string>GPU</string>
|
||||
<key>State</key>
|
||||
<false/>
|
||||
<key>Widgets</key>
|
||||
<dict>
|
||||
<key>mini</key>
|
||||
<dict>
|
||||
<key>Default</key>
|
||||
<true/>
|
||||
<key>Preview</key>
|
||||
<dict>
|
||||
<key>Value</key>
|
||||
<string>0.32</string>
|
||||
</dict>
|
||||
<key>Unsupported colors</key>
|
||||
<array>
|
||||
<string>pressure</string>
|
||||
</array>
|
||||
<key>Order</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>line_chart</key>
|
||||
<dict>
|
||||
<key>Default</key>
|
||||
<false/>
|
||||
<key>Color</key>
|
||||
<string>systemAccent</string>
|
||||
<key>Unsupported colors</key>
|
||||
<array>
|
||||
<string>pressure</string>
|
||||
</array>
|
||||
<key>Order</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>bar_chart</key>
|
||||
<dict>
|
||||
<key>Default</key>
|
||||
<false/>
|
||||
<key>Preview</key>
|
||||
<dict>
|
||||
<key>Value</key>
|
||||
<string>0.36,0.28,0.32,0.26</string>
|
||||
<key>Color</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>Unsupported colors</key>
|
||||
<array>
|
||||
<string>pressure</string>
|
||||
</array>
|
||||
<key>Order</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
110
Modules/GPU/main.swift
Normal file
110
Modules/GPU/main.swift
Normal file
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// main.swift
|
||||
// GPU
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 17/08/2020.
|
||||
// Using Swift 5.0.
|
||||
// Running on macOS 10.15.
|
||||
//
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import ModuleKit
|
||||
import StatsKit
|
||||
|
||||
public struct GPU_Info {
|
||||
public let name: String
|
||||
public let IOclass: String
|
||||
public var state: Bool = false
|
||||
|
||||
public var utilization: Double = 0
|
||||
public var temperature: Int = 0
|
||||
}
|
||||
|
||||
public struct GPUs: value_t {
|
||||
public var list: [GPU_Info] = []
|
||||
|
||||
internal func active() -> [GPU_Info] {
|
||||
return self.list.filter{ $0.state }
|
||||
}
|
||||
|
||||
internal func igpu() -> GPU_Info? {
|
||||
return self.active().first{ $0.IOclass == "IntelAccelerator" }
|
||||
}
|
||||
|
||||
public var widget_value: Double {
|
||||
get {
|
||||
return list[0].utilization
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class GPU: Module {
|
||||
private let smc: UnsafePointer<SMCService>?
|
||||
private let store: UnsafePointer<Store>
|
||||
|
||||
private var infoReader: InfoReader? = nil
|
||||
private var settingsView: Settings
|
||||
private var popupView: Popup = Popup()
|
||||
|
||||
private var selectedGPU: String = ""
|
||||
|
||||
public init(_ store: UnsafePointer<Store>, _ smc: UnsafePointer<SMCService>) {
|
||||
self.store = store
|
||||
self.smc = smc
|
||||
self.settingsView = Settings("GPU", store: store)
|
||||
|
||||
super.init(
|
||||
store: store,
|
||||
popup: self.popupView,
|
||||
settings: self.settingsView
|
||||
)
|
||||
guard self.available else { return }
|
||||
|
||||
self.infoReader = InfoReader()
|
||||
self.infoReader?.smc = smc
|
||||
self.selectedGPU = store.pointee.string(key: "\(self.config.name)_gpu", defaultValue: self.selectedGPU)
|
||||
|
||||
self.infoReader?.readyCallback = { [unowned self] in
|
||||
self.readyHandler()
|
||||
}
|
||||
self.infoReader?.callbackHandler = { [unowned self] value in
|
||||
self.infoCallback(value)
|
||||
}
|
||||
|
||||
self.settingsView.selectedGPUHandler = { [unowned self] value in
|
||||
self.selectedGPU = value
|
||||
self.infoReader?.read()
|
||||
}
|
||||
self.settingsView.setInterval = { [unowned self] value in
|
||||
self.infoReader?.setInterval(value)
|
||||
}
|
||||
|
||||
if let reader = self.infoReader {
|
||||
self.addReader(reader)
|
||||
}
|
||||
}
|
||||
|
||||
private func infoCallback(_ value: GPUs?) {
|
||||
guard value != nil else {
|
||||
return
|
||||
}
|
||||
|
||||
self.popupView.infoCallback(value!)
|
||||
self.settingsView.setList(value!)
|
||||
|
||||
let activeGPU = value!.active()
|
||||
let selectedGPU = activeGPU.first{ $0.name == self.selectedGPU } ?? value!.igpu() ?? value!.list[0]
|
||||
|
||||
if let widget = self.widget as? Mini {
|
||||
widget.setValue(selectedGPU.utilization, sufix: "%")
|
||||
}
|
||||
if let widget = self.widget as? LineChart {
|
||||
widget.setValue(selectedGPU.utilization)
|
||||
}
|
||||
if let widget = self.widget as? BarChart {
|
||||
widget.setValue([selectedGPU.utilization])
|
||||
}
|
||||
}
|
||||
}
|
||||
220
Modules/GPU/popup.swift
Normal file
220
Modules/GPU/popup.swift
Normal file
@@ -0,0 +1,220 @@
|
||||
//
|
||||
// popup.swift
|
||||
// GPU
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 17/08/2020.
|
||||
// Using Swift 5.0.
|
||||
// Running on macOS 10.15.
|
||||
//
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
import ModuleKit
|
||||
|
||||
internal class Popup: NSView {
|
||||
private var list: [String: GPUView] = [:]
|
||||
private let gpuViewHeight: CGFloat = 162
|
||||
|
||||
public init() {
|
||||
super.init(frame: NSRect(x: 0, y: 0, width: Constants.Popup.width, height: 0))
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
internal func infoCallback(_ value: GPUs) {
|
||||
if self.list.count != value.list.count {
|
||||
DispatchQueue.main.async(execute: {
|
||||
self.subviews.forEach{ $0.removeFromSuperview() }
|
||||
})
|
||||
self.list = [:]
|
||||
}
|
||||
|
||||
value.list.forEach { (gpu: GPU_Info) in
|
||||
if self.list[gpu.name] == nil {
|
||||
DispatchQueue.main.async(execute: {
|
||||
self.list[gpu.name] = GPUView(
|
||||
NSRect(x: 0, y: (self.gpuViewHeight + Constants.Popup.margins) * CGFloat(self.list.count), width: self.frame.width, height: self.gpuViewHeight),
|
||||
gpu: gpu
|
||||
)
|
||||
self.addSubview(self.list[gpu.name]!)
|
||||
})
|
||||
} else {
|
||||
self.list[gpu.name]?.update(gpu)
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async(execute: {
|
||||
let h: CGFloat = ((self.gpuViewHeight + Constants.Popup.margins) * CGFloat(self.list.count)) - Constants.Popup.margins
|
||||
if self.frame.size.height != h {
|
||||
self.setFrameSize(NSSize(width: self.frame.width, height: h))
|
||||
NotificationCenter.default.post(name: .updatePopupSize, object: nil, userInfo: ["module": "GPU"])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private class GPUView: NSView {
|
||||
private let height: CGFloat = 60
|
||||
private let margin: CGFloat = 4
|
||||
|
||||
private var value: GPU_Info
|
||||
|
||||
private var temperatureChart: LineChartView? = nil
|
||||
private var utilizationChart: LineChartView? = nil
|
||||
private var temperatureCirle: HalfCircleGraphView? = nil
|
||||
private var utilizationCircle: HalfCircleGraphView? = nil
|
||||
|
||||
private var stateView: NSView? = nil
|
||||
|
||||
public init(_ frame: NSRect, gpu: GPU_Info) {
|
||||
self.value = gpu
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.wantsLayer = true
|
||||
self.layer?.cornerRadius = 2
|
||||
|
||||
self.initName()
|
||||
self.initTemperature()
|
||||
self.initUtilization()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func initName() {
|
||||
let y: CGFloat = self.frame.height - 23
|
||||
let width: CGFloat = self.value.name.widthOfString(usingFont: NSFont.systemFont(ofSize: 12, weight: .medium)) + 16
|
||||
|
||||
let view: NSView = NSView(frame: NSRect(x: (self.frame.width - width)/2, y: y, width: width, height: 20))
|
||||
|
||||
let labelView: NSTextField = TextView(frame: NSRect(x: 0, y: (view.frame.height-15)/2, width: width - 8, height: 15))
|
||||
labelView.alignment = .center
|
||||
labelView.textColor = .secondaryLabelColor
|
||||
labelView.font = NSFont.systemFont(ofSize: 12, weight: .medium)
|
||||
labelView.stringValue = self.value.name
|
||||
|
||||
let stateView: NSView = NSView(frame: NSRect(x: width - 8, y: (view.frame.height-7)/2, width: 6, height: 6))
|
||||
stateView.wantsLayer = true
|
||||
stateView.layer?.backgroundColor = (self.value.state ? NSColor.systemGreen : NSColor.systemRed).cgColor
|
||||
stateView.toolTip = "GPU \(self.value.state ? "enabled" : "disabled")"
|
||||
stateView.layer?.cornerRadius = 4
|
||||
|
||||
view.addSubview(labelView)
|
||||
view.addSubview(stateView)
|
||||
|
||||
self.addSubview(view)
|
||||
self.stateView = stateView
|
||||
}
|
||||
|
||||
private func initTemperature() {
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: self.margin,
|
||||
y: self.height + (self.margin*2),
|
||||
width: self.frame.width - (self.margin*2),
|
||||
height: self.height
|
||||
))
|
||||
|
||||
let circleWidth: CGFloat = 70
|
||||
let circleSize: CGFloat = 44
|
||||
|
||||
let chartView: NSView = NSView(frame: NSRect(
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: view.frame.width - circleWidth,
|
||||
height: view.frame.height
|
||||
))
|
||||
chartView.wantsLayer = true
|
||||
chartView.layer?.backgroundColor = NSColor.lightGray.withAlphaComponent(0.1).cgColor
|
||||
chartView.layer?.cornerRadius = 3
|
||||
self.temperatureChart = LineChartView(frame: NSRect(x: 0, y: 0, width: chartView.frame.width, height: chartView.frame.height), num: 120)
|
||||
chartView.addSubview(self.temperatureChart!)
|
||||
|
||||
self.temperatureCirle = HalfCircleGraphView(frame: NSRect(
|
||||
x: (view.frame.width - circleWidth) + (circleWidth - circleSize)/2,
|
||||
y: (view.frame.height - circleSize)/2 - 3,
|
||||
width: circleSize,
|
||||
height: circleSize
|
||||
))
|
||||
self.temperatureCirle!.toolTip = "GPU temperature"
|
||||
|
||||
view.addSubview(chartView)
|
||||
view.addSubview(self.temperatureCirle!)
|
||||
|
||||
self.temperatureCirle?.setValue(Double(self.value.temperature))
|
||||
let formatter = MeasurementFormatter()
|
||||
formatter.numberFormatter.maximumFractionDigits = 0
|
||||
let measurement = Measurement(value: Double(self.value.temperature), unit: UnitTemperature.celsius)
|
||||
self.temperatureCirle?.setText(formatter.string(from: measurement))
|
||||
self.temperatureChart?.addValue(Double(self.value.temperature) / 100)
|
||||
|
||||
self.addSubview(view)
|
||||
}
|
||||
|
||||
private func initUtilization() {
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: self.margin,
|
||||
y: self.margin,
|
||||
width: self.frame.width - (self.margin*2),
|
||||
height: self.height
|
||||
))
|
||||
|
||||
let circleWidth: CGFloat = 70
|
||||
let circleSize: CGFloat = 44
|
||||
|
||||
let chartView: NSView = NSView(frame: NSRect(
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: view.frame.width - circleWidth,
|
||||
height: view.frame.height
|
||||
))
|
||||
chartView.wantsLayer = true
|
||||
chartView.layer?.backgroundColor = NSColor.lightGray.withAlphaComponent(0.1).cgColor
|
||||
chartView.layer?.cornerRadius = 3
|
||||
self.utilizationChart = LineChartView(frame: NSRect(x: 0, y: 0, width: chartView.frame.width, height: chartView.frame.height), num: 120)
|
||||
chartView.addSubview(self.utilizationChart!)
|
||||
|
||||
self.utilizationCircle = HalfCircleGraphView(frame: NSRect(
|
||||
x: (view.frame.width - circleWidth) + (circleWidth - circleSize)/2,
|
||||
y: (view.frame.height - circleSize)/2 - 3,
|
||||
width: circleSize,
|
||||
height: circleSize
|
||||
))
|
||||
self.utilizationCircle!.toolTip = "GPU utilization"
|
||||
|
||||
view.addSubview(chartView)
|
||||
view.addSubview(self.utilizationCircle!)
|
||||
|
||||
self.utilizationCircle?.setValue(self.value.utilization)
|
||||
self.utilizationCircle?.setText("\(Int(self.value.utilization*100))%")
|
||||
self.utilizationChart?.addValue(self.value.utilization)
|
||||
|
||||
self.addSubview(view)
|
||||
}
|
||||
|
||||
public func update(_ gpu: GPU_Info) {
|
||||
DispatchQueue.main.async(execute: {
|
||||
if (self.window?.isVisible ?? false) {
|
||||
self.stateView?.layer?.backgroundColor = (gpu.state ? NSColor.systemGreen : NSColor.systemRed).cgColor
|
||||
self.stateView?.toolTip = "GPU \(gpu.state ? "enabled" : "disabled")"
|
||||
|
||||
self.temperatureCirle?.setValue(Double(gpu.temperature))
|
||||
let formatter = MeasurementFormatter()
|
||||
formatter.numberFormatter.maximumFractionDigits = 0
|
||||
let measurement = Measurement(value: Double(gpu.temperature), unit: UnitTemperature.celsius)
|
||||
self.temperatureCirle?.setText(formatter.string(from: measurement))
|
||||
|
||||
self.utilizationCircle?.setValue(gpu.utilization)
|
||||
self.utilizationCircle?.setText("\(Int(gpu.utilization*100))%")
|
||||
}
|
||||
|
||||
self.temperatureChart?.addValue(Double(gpu.temperature) / 100)
|
||||
self.utilizationChart?.addValue(gpu.utilization)
|
||||
})
|
||||
}
|
||||
}
|
||||
98
Modules/GPU/reader.swift
Normal file
98
Modules/GPU/reader.swift
Normal file
@@ -0,0 +1,98 @@
|
||||
//
|
||||
// reader.swift
|
||||
// GPU
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 17/08/2020.
|
||||
// Using Swift 5.0.
|
||||
// Running on macOS 10.15.
|
||||
//
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
import ModuleKit
|
||||
import os.log
|
||||
|
||||
internal class InfoReader: Reader<GPUs> {
|
||||
internal var smc: UnsafePointer<SMCService>? = nil
|
||||
|
||||
private var gpus: GPUs = GPUs()
|
||||
private var devices: [NSDictionary]? = nil
|
||||
|
||||
public override func setup() {
|
||||
guard let devices = fetchIOService("IOPCIDevice") else {
|
||||
return
|
||||
}
|
||||
|
||||
self.devices = devices.filter{ $0.object(forKey: "IOName") as? String == "display" }
|
||||
}
|
||||
|
||||
public override func read() {
|
||||
guard let acceletators = fetchIOService(kIOAcceleratorClassName) else {
|
||||
return
|
||||
}
|
||||
|
||||
acceletators.forEach { (accelerator: NSDictionary) in
|
||||
guard let matchedGPU = self.devices?.first(where: { (gpu: NSDictionary) -> Bool in
|
||||
guard let deviceID = gpu["device-id"] as? Data, let vendorID = gpu["vendor-id"] as? Data else {
|
||||
return false
|
||||
}
|
||||
|
||||
let pciMatch = "0x" + Data([deviceID[1], deviceID[0], vendorID[1], vendorID[0]]).map { String(format: "%02hhX", $0) }.joined()
|
||||
let accMatch = accelerator["IOPCIMatch"] as? String ?? accelerator["IOPCIPrimaryMatch"] as? String ?? ""
|
||||
|
||||
return accMatch.range(of: pciMatch) != nil
|
||||
}) else { return }
|
||||
|
||||
guard let agcInfo = accelerator["AGCInfo"] as? [String:Int] else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let stats = accelerator["PerformanceStatistics"] as? [String:Any] else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let model = matchedGPU.object(forKey: "model") as? Data else {
|
||||
return
|
||||
}
|
||||
let modelName = String(data: model, encoding: .ascii)!.replacingOccurrences(of: "\0", with: "")
|
||||
|
||||
guard let IOClass = accelerator.object(forKey: "IOClass") as? String else {
|
||||
return
|
||||
}
|
||||
|
||||
if self.gpus.list.first(where: { $0.name == modelName }) == nil {
|
||||
self.gpus.list.append(GPU_Info(name: modelName, IOclass: IOClass))
|
||||
}
|
||||
|
||||
guard let idx = self.gpus.list.firstIndex(where: { $0.name == modelName }) else {
|
||||
return
|
||||
}
|
||||
|
||||
let utilization = stats["Device Utilization %"] as? Int ?? 0
|
||||
// let totalVram = (accelerator["VRAM,totalMB"] as? Int ?? matchedGPU["VRAM,totalMB"] as? Int ?? 0) * 1000000
|
||||
// let freeVram = stats["vramFreeBytes"] as? Int ?? 0
|
||||
// let coreClock = stats["Core Clock(MHz)"] as? Int ?? 0
|
||||
var temperature = stats["Temperature(C)"] as? Int ?? 0
|
||||
|
||||
if IOClass == "IntelAccelerator" {
|
||||
if temperature == 0 {
|
||||
if let tmp = self.smc?.pointee.getValue("TCGC") {
|
||||
temperature = Int(tmp)
|
||||
} else if let tmp = self.smc?.pointee.getValue("TG0D") {
|
||||
temperature = Int(tmp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.gpus.list[idx].state = agcInfo["poweredOffByAGC"] == 0
|
||||
|
||||
self.gpus.list[idx].utilization = utilization == 0 ? 0 : Double(utilization)/100
|
||||
self.gpus.list[idx].temperature = temperature
|
||||
}
|
||||
|
||||
self.gpus.list.sort{ !$0.state && $1.state }
|
||||
self.callback(self.gpus)
|
||||
}
|
||||
}
|
||||
126
Modules/GPU/settings.swift
Normal file
126
Modules/GPU/settings.swift
Normal file
@@ -0,0 +1,126 @@
|
||||
//
|
||||
// settings.swift
|
||||
// GPU
|
||||
//
|
||||
// Created by Serhiy Mytrovtsiy on 17/08/2020.
|
||||
// Using Swift 5.0.
|
||||
// Running on macOS 10.15.
|
||||
//
|
||||
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
import StatsKit
|
||||
import ModuleKit
|
||||
|
||||
internal class Settings: NSView, Settings_v {
|
||||
private var updateIntervalValue: String = "1"
|
||||
private let listOfUpdateIntervals: [String] = ["1", "2", "3", "5", "10", "15", "30"]
|
||||
private var selectedGPU: String
|
||||
|
||||
private let title: String
|
||||
private let store: UnsafePointer<Store>
|
||||
|
||||
public var selectedGPUHandler: (String) -> Void = {_ in }
|
||||
public var callback: (() -> Void) = {}
|
||||
public var setInterval: ((_ value: Double) -> Void) = {_ in }
|
||||
|
||||
private var hyperthreadView: NSView? = nil
|
||||
|
||||
private var button: NSPopUpButton?
|
||||
|
||||
public init(_ title: String, store: UnsafePointer<Store>) {
|
||||
self.title = title
|
||||
self.store = store
|
||||
self.selectedGPU = store.pointee.string(key: "\(self.title)_gpu", defaultValue: "")
|
||||
self.updateIntervalValue = store.pointee.string(key: "\(self.title)_updateInterval", defaultValue: self.updateIntervalValue)
|
||||
|
||||
super.init(frame: CGRect(
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: Constants.Settings.width - (Constants.Settings.margin*2),
|
||||
height: 0
|
||||
))
|
||||
|
||||
self.wantsLayer = true
|
||||
self.canDrawConcurrently = true
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func load(widget: widget_t) {
|
||||
self.subviews.forEach{ $0.removeFromSuperview() }
|
||||
|
||||
let rowHeight: CGFloat = 30
|
||||
let num: CGFloat = 1
|
||||
|
||||
self.addSubview(SelectTitleRow(
|
||||
frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin + (rowHeight + Constants.Settings.margin) * num, width: self.frame.width - (Constants.Settings.margin*2), height: rowHeight),
|
||||
title: "Update interval",
|
||||
action: #selector(changeUpdateInterval),
|
||||
items: self.listOfUpdateIntervals.map{ "\($0) sec" },
|
||||
selected: "\(self.updateIntervalValue) sec"
|
||||
))
|
||||
|
||||
self.addGPUSelector()
|
||||
|
||||
self.setFrameSize(NSSize(width: self.frame.width, height: (rowHeight*(num+1)) + (Constants.Settings.margin*(2+num))))
|
||||
}
|
||||
|
||||
private func addGPUSelector() {
|
||||
let view: NSView = NSView(frame: NSRect(
|
||||
x: Constants.Settings.margin,
|
||||
y: Constants.Settings.margin,
|
||||
width: self.frame.width - Constants.Settings.margin*2,
|
||||
height: 30
|
||||
))
|
||||
|
||||
let rowTitle: NSTextField = LabelField(frame: NSRect(x: 0, y: (view.frame.height - 16)/2, width: view.frame.width - 52, height: 17), "GPU to show")
|
||||
rowTitle.font = NSFont.systemFont(ofSize: 13, weight: .light)
|
||||
rowTitle.textColor = .textColor
|
||||
|
||||
self.button = NSPopUpButton(frame: NSRect(x: view.frame.width - 200, y: -1, width: 200, height: 30))
|
||||
self.button!.target = self
|
||||
self.button?.action = #selector(self.handleSelection)
|
||||
|
||||
view.addSubview(rowTitle)
|
||||
view.addSubview(self.button!)
|
||||
|
||||
self.addSubview(view)
|
||||
}
|
||||
|
||||
internal func setList(_ list: GPUs) {
|
||||
let disks = list.active().map{ $0.name }
|
||||
DispatchQueue.main.async(execute: {
|
||||
if self.button?.itemTitles.count != disks.count {
|
||||
self.button?.removeAllItems()
|
||||
}
|
||||
|
||||
if disks != self.button?.itemTitles {
|
||||
self.button?.addItems(withTitles: disks)
|
||||
if self.selectedGPU != "" {
|
||||
self.button?.selectItem(withTitle: self.selectedGPU)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@objc private func changeUpdateInterval(_ sender: NSMenuItem) {
|
||||
let newUpdateInterval = sender.title.replacingOccurrences(of: " sec", with: "")
|
||||
self.updateIntervalValue = newUpdateInterval
|
||||
store.pointee.set(key: "\(self.title)_updateInterval", value: self.updateIntervalValue)
|
||||
|
||||
if let value = Double(self.updateIntervalValue) {
|
||||
self.setInterval(value)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func handleSelection(_ sender: NSPopUpButton) {
|
||||
guard let item = sender.selectedItem else { return }
|
||||
self.selectedGPU = item.title
|
||||
self.store.pointee.set(key: "\(self.title)_gpu", value: item.title)
|
||||
self.selectedGPUHandler(item.title)
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ internal class Popup: NSView {
|
||||
private var circle: CircleGraphView? = nil
|
||||
private var level: PressureView? = nil
|
||||
private var initialized: Bool = false
|
||||
private var processesInitialized: Bool = false
|
||||
|
||||
private var processes: [ProcessView] = []
|
||||
|
||||
@@ -157,34 +158,39 @@ internal class Popup: NSView {
|
||||
self.inactiveField?.stringValue = Units(bytes: Int64(value.inactive)).getReadableMemory()
|
||||
self.wiredField?.stringValue = Units(bytes: Int64(value.wired)).getReadableMemory()
|
||||
self.compressedField?.stringValue = Units(bytes: Int64(value.compressed)).getReadableMemory()
|
||||
|
||||
|
||||
self.totalField?.stringValue = Units(bytes: Int64(value.total)).getReadableMemory()
|
||||
self.usedField?.stringValue = Units(bytes: Int64(value.used)).getReadableMemory()
|
||||
self.freeField?.stringValue = Units(bytes: Int64(value.free)).getReadableMemory()
|
||||
|
||||
self.circle?.setValue(value.usage)
|
||||
self.circle?.setSegments([
|
||||
circle_segment(value: value.active/value.total, color: NSColor.systemBlue),
|
||||
circle_segment(value: value.wired/value.total, color: NSColor.systemOrange),
|
||||
circle_segment(value: value.compressed/value.total, color: NSColor.systemPink)
|
||||
])
|
||||
self.level?.setLevel(value.pressureLevel)
|
||||
|
||||
self.initialized = true
|
||||
}
|
||||
|
||||
self.circle?.setValue(value.usage)
|
||||
self.circle?.setSegments([
|
||||
circle_segment(value: value.active/value.total, color: NSColor.systemBlue),
|
||||
circle_segment(value: value.wired/value.total, color: NSColor.systemOrange),
|
||||
circle_segment(value: value.compressed/value.total, color: NSColor.systemPink)
|
||||
])
|
||||
self.chart?.addValue(value.usage)
|
||||
self.level?.setLevel(value.pressureLevel)
|
||||
})
|
||||
}
|
||||
|
||||
public func processCallback(_ list: [TopProcess]) {
|
||||
DispatchQueue.main.async(execute: {
|
||||
for i in 0..<list.count {
|
||||
let process = list[i]
|
||||
let index = list.count-i-1
|
||||
if self.processes.indices.contains(index) {
|
||||
self.processes[index].label = process.name != nil ? process.name! : process.command
|
||||
self.processes[index].value = Units(bytes: Int64(process.usage)).getReadableMemory()
|
||||
self.processes[index].icon = process.icon
|
||||
if (self.window?.isVisible ?? false) || !self.processesInitialized {
|
||||
for i in 0..<list.count {
|
||||
let process = list[i]
|
||||
let index = list.count-i-1
|
||||
if self.processes.indices.contains(index) {
|
||||
self.processes[index].label = process.name != nil ? process.name! : process.command
|
||||
self.processes[index].value = Units(bytes: Int64(process.usage)).getReadableMemory()
|
||||
self.processes[index].icon = process.icon
|
||||
}
|
||||
}
|
||||
|
||||
self.processesInitialized = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ internal class Popup: NSView {
|
||||
private var macAdressField: ValueField? = nil
|
||||
|
||||
private var initialized: Bool = false
|
||||
private var processesInitialized: Bool = false
|
||||
|
||||
private var chart: MultiLinesChartView? = nil
|
||||
private var processes: [NetworkProcessView] = []
|
||||
@@ -222,44 +223,42 @@ internal class Popup: NSView {
|
||||
|
||||
public func usageCallback(_ value: Network_Usage) {
|
||||
DispatchQueue.main.async(execute: {
|
||||
if !(self.window?.isVisible ?? false) && self.initialized {
|
||||
return
|
||||
}
|
||||
|
||||
self.uploadValue = value.upload
|
||||
self.downloadValue = value.download
|
||||
self.setUploadDownloadFields()
|
||||
|
||||
if let interface = value.interface {
|
||||
self.interfaceField?.stringValue = "\(interface.displayName) (\(interface.BSDName))"
|
||||
self.macAdressField?.stringValue = interface.address
|
||||
} else {
|
||||
self.interfaceField?.stringValue = "Unknown"
|
||||
self.macAdressField?.stringValue = "Unknown"
|
||||
}
|
||||
|
||||
if value.connectionType == .wifi {
|
||||
self.ssidField?.stringValue = value.ssid ?? "Unknown"
|
||||
} else {
|
||||
self.ssidField?.stringValue = "Unavailable"
|
||||
}
|
||||
|
||||
if self.publicIPField?.stringValue != value.raddr {
|
||||
if value.raddr == nil {
|
||||
self.publicIPField?.stringValue = "Unknown"
|
||||
if (self.window?.isVisible ?? false) || !self.initialized {
|
||||
self.uploadValue = value.upload
|
||||
self.downloadValue = value.download
|
||||
self.setUploadDownloadFields()
|
||||
|
||||
if let interface = value.interface {
|
||||
self.interfaceField?.stringValue = "\(interface.displayName) (\(interface.BSDName))"
|
||||
self.macAdressField?.stringValue = interface.address
|
||||
} else {
|
||||
if value.countryCode == nil {
|
||||
self.publicIPField?.stringValue = value.raddr!
|
||||
self.interfaceField?.stringValue = "Unknown"
|
||||
self.macAdressField?.stringValue = "Unknown"
|
||||
}
|
||||
|
||||
if value.connectionType == .wifi {
|
||||
self.ssidField?.stringValue = value.ssid ?? "Unknown"
|
||||
} else {
|
||||
self.ssidField?.stringValue = "Unavailable"
|
||||
}
|
||||
|
||||
if self.publicIPField?.stringValue != value.raddr {
|
||||
if value.raddr == nil {
|
||||
self.publicIPField?.stringValue = "Unknown"
|
||||
} else {
|
||||
self.publicIPField?.stringValue = "\(value.raddr!) (\(value.countryCode!))"
|
||||
if value.countryCode == nil {
|
||||
self.publicIPField?.stringValue = value.raddr!
|
||||
} else {
|
||||
self.publicIPField?.stringValue = "\(value.raddr!) (\(value.countryCode!))"
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.localIPField?.stringValue != value.laddr {
|
||||
self.localIPField?.stringValue = value.laddr ?? "Unknown"
|
||||
}
|
||||
|
||||
self.initialized = true
|
||||
}
|
||||
if self.localIPField?.stringValue != value.laddr {
|
||||
self.localIPField?.stringValue = value.laddr ?? "Unknown"
|
||||
}
|
||||
|
||||
self.initialized = true
|
||||
|
||||
self.chart?.addValues([Double(value.upload), Double(value.download)])
|
||||
})
|
||||
@@ -267,14 +266,16 @@ internal class Popup: NSView {
|
||||
|
||||
public func processCallback(_ list: [Network_Process]) {
|
||||
DispatchQueue.main.async(execute: {
|
||||
for i in 0..<list.count {
|
||||
let process = list[i]
|
||||
let index = list.count-i-1
|
||||
if self.processes.indices.contains(index) {
|
||||
self.processes[index].label = process.name
|
||||
self.processes[index].upload = Units(bytes: Int64(process.upload)).getReadableSpeed()
|
||||
self.processes[index].download = Units(bytes: Int64(process.download)).getReadableSpeed()
|
||||
self.processes[index].icon = process.icon
|
||||
if (self.window?.isVisible ?? false) {
|
||||
for i in 0..<list.count {
|
||||
let process = list[i]
|
||||
let index = list.count-i-1
|
||||
if self.processes.indices.contains(index) {
|
||||
self.processes[index].label = process.name
|
||||
self.processes[index].upload = Units(bytes: Int64(process.upload)).getReadableSpeed()
|
||||
self.processes[index].download = Units(bytes: Int64(process.download)).getReadableSpeed()
|
||||
self.processes[index].icon = process.icon
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -58,13 +58,13 @@ internal class Settings: NSView, Settings_v {
|
||||
}
|
||||
|
||||
private func addNetworkSelector() {
|
||||
let view: NSView = NSView(frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin, width: self.frame.width, height: 29))
|
||||
let view: NSView = NSView(frame: NSRect(x: Constants.Settings.margin, y: Constants.Settings.margin, width: self.frame.width, height: 30))
|
||||
|
||||
let rowTitle: NSTextField = LabelField(frame: NSRect(x: 0, y: (view.frame.height - 16)/2, width: view.frame.width - 52, height: 17), "Network interface")
|
||||
rowTitle.font = NSFont.systemFont(ofSize: 13, weight: .light)
|
||||
rowTitle.textColor = .textColor
|
||||
|
||||
self.button = NSPopUpButton(frame: NSRect(x: view.frame.width - 200 - Constants.Settings.margin*2, y: -1, width: 200, height: 30))
|
||||
self.button = NSPopUpButton(frame: NSRect(x: view.frame.width - 200 - Constants.Settings.margin*2, y: 0, width: 200, height: 30))
|
||||
self.button!.target = self
|
||||
self.button?.action = #selector(self.handleSelection)
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ let SensorsList: [Sensor_t] = [
|
||||
Sensor_t(key: "Th3H", name: "Heatpipe 4", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TZ0C", name: "Termal zone 1", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TZ1C", name: "Termal zone 2", group: SensorGroup.Sensor.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
|
||||
Sensor_t(key: "TC0E", name: "CPU 1", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TC0F", name: "CPU 2", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TC0D", name: "CPU die", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
@@ -112,7 +112,7 @@ let SensorsList: [Sensor_t] = [
|
||||
Sensor_t(key: "TC0H", name: "CPU heatsink", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TC0P", name: "CPU proximity", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TCAD", name: "CPU package", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
|
||||
Sensor_t(key: "TC0c", name: "CPU core 1", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TC1c", name: "CPU core 2", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TC2c", name: "CPU core 3", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
@@ -129,12 +129,12 @@ let SensorsList: [Sensor_t] = [
|
||||
Sensor_t(key: "TC13c", name: "CPU core 14", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TC14c", name: "CPU core 15", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TC15c", name: "CPU core 16", group: SensorGroup.CPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
|
||||
Sensor_t(key: "TCGC", name: "GPU Intel Graphics", group: SensorGroup.GPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TG0D", name: "GPU die", group: SensorGroup.GPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TG0H", name: "GPU heatsink", group: SensorGroup.GPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TG0P", name: "GPU proximity", group: SensorGroup.GPU.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
|
||||
Sensor_t(key: "Tm0P", name: "Mainboard", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "Tp0P", name: "Powerboard", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TB1T", name: "Battery", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
@@ -144,11 +144,11 @@ let SensorsList: [Sensor_t] = [
|
||||
Sensor_t(key: "TI1P", name: "Thunderbold 2", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TI2P", name: "Thunderbold 3", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TI3P", name: "Thunderbold 4", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
|
||||
Sensor_t(key: "TN0D", name: "Northbridge die", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TN0H", name: "Northbridge heatsink", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
Sensor_t(key: "TN0P", name: "Northbridge proximity", group: SensorGroup.System.rawValue, type: SensorType.Temperature.rawValue),
|
||||
|
||||
|
||||
/// Voltage
|
||||
Sensor_t(key: "VCAC", name: "CPU IA", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
Sensor_t(key: "VCSC", name: "CPU System Agent", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
@@ -168,13 +168,13 @@ let SensorsList: [Sensor_t] = [
|
||||
Sensor_t(key: "VC13C", name: "CPU Core 14", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
Sensor_t(key: "VC14C", name: "CPU Core 15", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
Sensor_t(key: "VC15C", name: "CPU Core 16", group: SensorGroup.CPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
|
||||
|
||||
Sensor_t(key: "VCTC", name: "GPU Intel Graphics", group: SensorGroup.GPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
Sensor_t(key: "VG0C", name: "GPU", group: SensorGroup.GPU.rawValue, type: SensorType.Voltage.rawValue),
|
||||
|
||||
|
||||
Sensor_t(key: "VM0R", name: "Memory", group: SensorGroup.System.rawValue, type: SensorType.Voltage.rawValue),
|
||||
Sensor_t(key: "Vb0R", name: "CMOS", group: SensorGroup.System.rawValue, type: SensorType.Voltage.rawValue),
|
||||
|
||||
|
||||
Sensor_t(key: "VD0R", name: "DC In", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
Sensor_t(key: "VP0R", name: "12V rail", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
Sensor_t(key: "Vp0C", name: "12V vcc", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
@@ -183,7 +183,7 @@ let SensorsList: [Sensor_t] = [
|
||||
Sensor_t(key: "VV1S", name: "5V", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
Sensor_t(key: "VV9S", name: "12V", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
Sensor_t(key: "VeES", name: "PCI 12V", group: SensorGroup.Sensor.rawValue, type: SensorType.Voltage.rawValue),
|
||||
|
||||
|
||||
/// Power
|
||||
Sensor_t(key: "PC0C", name: "CPU Core", group: SensorGroup.CPU.rawValue, type: SensorType.Power.rawValue),
|
||||
Sensor_t(key: "PCAM", name: "CPU Core (IMON)", group: SensorGroup.CPU.rawValue, type: SensorType.Power.rawValue),
|
||||
@@ -193,7 +193,7 @@ let SensorsList: [Sensor_t] = [
|
||||
Sensor_t(key: "PCPR", name: "CPU Package total (SMC)", group: SensorGroup.CPU.rawValue, type: SensorType.Power.rawValue),
|
||||
Sensor_t(key: "PC0R", name: "CPU Computing high side", group: SensorGroup.CPU.rawValue, type: SensorType.Power.rawValue),
|
||||
Sensor_t(key: "PC0G", name: "CPU GFX", group: SensorGroup.CPU.rawValue, type: SensorType.Power.rawValue),
|
||||
|
||||
|
||||
Sensor_t(key: "PCPG", name: "GPU Intel Graphics", group: SensorGroup.GPU.rawValue, type: SensorType.Power.rawValue),
|
||||
Sensor_t(key: "PG0R", name: "GPU", group: SensorGroup.GPU.rawValue, type: SensorType.Power.rawValue),
|
||||
Sensor_t(key: "PCGC", name: "Intel GPU", group: SensorGroup.GPU.rawValue, type: SensorType.Power.rawValue),
|
||||
@@ -203,7 +203,7 @@ let SensorsList: [Sensor_t] = [
|
||||
Sensor_t(key: "PPBR", name: "Battery", group: SensorGroup.Sensor.rawValue, type: SensorType.Power.rawValue),
|
||||
Sensor_t(key: "PDTR", name: "DC In", group: SensorGroup.Sensor.rawValue, type: SensorType.Power.rawValue),
|
||||
Sensor_t(key: "PSTR", name: "System total", group: SensorGroup.Sensor.rawValue, type: SensorType.Power.rawValue),
|
||||
|
||||
|
||||
/// Frequency
|
||||
Sensor_t(key: "FRC0", name: "CPU 1", group: SensorGroup.CPU.rawValue, type: SensorType.Frequency.rawValue),
|
||||
Sensor_t(key: "FRC1", name: "CPU 2", group: SensorGroup.CPU.rawValue, type: SensorType.Frequency.rawValue),
|
||||
@@ -221,11 +221,11 @@ let SensorsList: [Sensor_t] = [
|
||||
Sensor_t(key: "FRC13", name: "CPU 14", group: SensorGroup.CPU.rawValue, type: SensorType.Frequency.rawValue),
|
||||
Sensor_t(key: "FRC14", name: "CPU 15", group: SensorGroup.CPU.rawValue, type: SensorType.Frequency.rawValue),
|
||||
Sensor_t(key: "FRC15", name: "CPU 16", group: SensorGroup.CPU.rawValue, type: SensorType.Frequency.rawValue),
|
||||
|
||||
|
||||
Sensor_t(key: "CG0C", name: "GPU", group: SensorGroup.GPU.rawValue, type: SensorType.Frequency.rawValue),
|
||||
Sensor_t(key: "CG0S", name: "GPU shader", group: SensorGroup.GPU.rawValue, type: SensorType.Frequency.rawValue),
|
||||
Sensor_t(key: "CG0M", name: "GPU memory", group: SensorGroup.GPU.rawValue, type: SensorType.Frequency.rawValue),
|
||||
|
||||
|
||||
/// Battery
|
||||
Sensor_t(key: "B0AV", name: "Voltage", group: SensorGroup.Sensor.rawValue, type: SensorType.Battery.rawValue),
|
||||
Sensor_t(key: "B0AC", name: "Amperage", group: SensorGroup.Sensor.rawValue, type: SensorType.Battery.rawValue),
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
9A3E17E8247AA8E100449CD1 /* Speed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A3E17E7247AA8E100449CD1 /* Speed.swift */; };
|
||||
9A3E17EA247B07BF00449CD1 /* popup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A3E17E9247B07BF00449CD1 /* popup.swift */; };
|
||||
9A41530C24ABC3AF00A2BDA7 /* Memory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A41530B24ABC3AF00A2BDA7 /* Memory.swift */; };
|
||||
9A53EBF924EAFA5200648841 /* settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A53EBF824EAFA5200648841 /* settings.swift */; };
|
||||
9A53EBFB24EB041E00648841 /* popup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A53EBFA24EB041E00648841 /* popup.swift */; };
|
||||
9A58DE9E24B363D800716A9F /* popup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A58DE9D24B363D800716A9F /* popup.swift */; };
|
||||
9A58DEA024B363F300716A9F /* settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A58DE9F24B363F300716A9F /* settings.swift */; };
|
||||
9A58DEA424B3647600716A9F /* settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A58DEA324B3647600716A9F /* settings.swift */; };
|
||||
@@ -57,6 +59,15 @@
|
||||
9A81C76B2449AE9400825D92 /* StatsKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A0C82DA24460F7200FAE3D4 /* StatsKit.framework */; };
|
||||
9A81C76C2449AE9400825D92 /* StatsKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9A0C82DA24460F7200FAE3D4 /* StatsKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
9A81C7702449B8D500825D92 /* Charts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A81C76F2449B8D500825D92 /* Charts.swift */; };
|
||||
9A90E19024EAD2BB00471E9A /* GPU.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A90E18924EAD2BB00471E9A /* GPU.framework */; };
|
||||
9A90E19124EAD2BB00471E9A /* GPU.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9A90E18924EAD2BB00471E9A /* GPU.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
9A90E19624EAD35F00471E9A /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A90E19524EAD35F00471E9A /* main.swift */; };
|
||||
9A90E19824EAD3B000471E9A /* config.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9A90E19724EAD3B000471E9A /* config.plist */; };
|
||||
9A90E19924EAD3E300471E9A /* ModuleKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AABEADD243FB13500668CB0 /* ModuleKit.framework */; };
|
||||
9A90E19A24EAD3E300471E9A /* ModuleKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9AABEADD243FB13500668CB0 /* ModuleKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
9A90E19D24EAD3E300471E9A /* StatsKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A0C82DA24460F7200FAE3D4 /* StatsKit.framework */; };
|
||||
9A90E19E24EAD3E300471E9A /* StatsKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9A0C82DA24460F7200FAE3D4 /* StatsKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
9A90E1A324EAD66600471E9A /* reader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A90E1A224EAD66600471E9A /* reader.swift */; };
|
||||
9A944D55244920690058F32A /* reader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A944D54244920690058F32A /* reader.swift */; };
|
||||
9A944D59244920FE0058F32A /* readers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A944D58244920FE0058F32A /* readers.swift */; };
|
||||
9A944D5B244925720058F32A /* widget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A944D5A244925720058F32A /* widget.swift */; };
|
||||
@@ -191,6 +202,27 @@
|
||||
remoteGlobalIDString = 9A0C82D924460F7200FAE3D4;
|
||||
remoteInfo = StatsKit;
|
||||
};
|
||||
9A90E18E24EAD2BB00471E9A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 9A1410ED229E721100D29793 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 9A90E18824EAD2BB00471E9A;
|
||||
remoteInfo = GPU;
|
||||
};
|
||||
9A90E19B24EAD3E300471E9A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 9A1410ED229E721100D29793 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 9AABEADC243FB13500668CB0;
|
||||
remoteInfo = ModuleKit;
|
||||
};
|
||||
9A90E19F24EAD3E300471E9A /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 9A1410ED229E721100D29793 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 9A0C82D924460F7200FAE3D4;
|
||||
remoteInfo = StatsKit;
|
||||
};
|
||||
9AABEAE2243FB13500668CB0 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 9A1410ED229E721100D29793 /* Project object */;
|
||||
@@ -310,6 +342,7 @@
|
||||
9AABEAE5243FB13500668CB0 /* ModuleKit.framework in Embed Frameworks */,
|
||||
9A3E17D4247A94AF00449CD1 /* Net.framework in Embed Frameworks */,
|
||||
9A0C82E224460F7200FAE3D4 /* StatsKit.framework in Embed Frameworks */,
|
||||
9A90E19124EAD2BB00471E9A /* GPU.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@@ -326,6 +359,18 @@
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9A90E1A124EAD3E300471E9A /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
9A90E19A24EAD3E300471E9A /* ModuleKit.framework in Embed Frameworks */,
|
||||
9A90E19E24EAD3E300471E9A /* StatsKit.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9AABEB76243FCEEF00668CB0 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 12;
|
||||
@@ -419,6 +464,8 @@
|
||||
9A3E17E9247B07BF00449CD1 /* popup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = popup.swift; sourceTree = "<group>"; };
|
||||
9A41530B24ABC3AF00A2BDA7 /* Memory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Memory.swift; sourceTree = "<group>"; };
|
||||
9A5349CD23D8832E00C23824 /* Reachability.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Reachability.framework; path = Carthage/Build/Mac/Reachability.framework; sourceTree = "<group>"; };
|
||||
9A53EBF824EAFA5200648841 /* settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = settings.swift; sourceTree = "<group>"; };
|
||||
9A53EBFA24EB041E00648841 /* popup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = popup.swift; sourceTree = "<group>"; };
|
||||
9A58DE9D24B363D800716A9F /* popup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = popup.swift; sourceTree = "<group>"; };
|
||||
9A58DE9F24B363F300716A9F /* settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = settings.swift; sourceTree = "<group>"; };
|
||||
9A58DEA324B3647600716A9F /* settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = settings.swift; sourceTree = "<group>"; };
|
||||
@@ -437,6 +484,11 @@
|
||||
9A81C7672449A43600825D92 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
9A81C7682449A43600825D92 /* readers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = readers.swift; sourceTree = "<group>"; };
|
||||
9A81C76F2449B8D500825D92 /* Charts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Charts.swift; sourceTree = "<group>"; };
|
||||
9A90E18924EAD2BB00471E9A /* GPU.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GPU.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
9A90E18C24EAD2BB00471E9A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9A90E19524EAD35F00471E9A /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
9A90E19724EAD3B000471E9A /* config.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = config.plist; sourceTree = "<group>"; };
|
||||
9A90E1A224EAD66600471E9A /* reader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = reader.swift; sourceTree = "<group>"; };
|
||||
9A944D54244920690058F32A /* reader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = reader.swift; sourceTree = "<group>"; };
|
||||
9A944D58244920FE0058F32A /* readers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = readers.swift; sourceTree = "<group>"; };
|
||||
9A944D5A244925720058F32A /* widget.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = widget.swift; sourceTree = "<group>"; };
|
||||
@@ -508,6 +560,7 @@
|
||||
9A0C82E124460F7200FAE3D4 /* StatsKit.framework in Frameworks */,
|
||||
9A3E17D3247A94AF00449CD1 /* Net.framework in Frameworks */,
|
||||
9AABEB6B243FCE8A00668CB0 /* CPU.framework in Frameworks */,
|
||||
9A90E19024EAD2BB00471E9A /* GPU.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -537,6 +590,15 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9A90E18624EAD2BB00471E9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9A90E19924EAD3E300471E9A /* ModuleKit.framework in Frameworks */,
|
||||
9A90E19D24EAD3E300471E9A /* StatsKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9AABEADA243FB13500668CB0 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -628,6 +690,7 @@
|
||||
9A3E17CC247A94AF00449CD1 /* Net.framework */,
|
||||
9ABFF8F6248BEBCB00C9041A /* Battery.framework */,
|
||||
9AE29AD5249A50350071B02D /* Sensors.framework */,
|
||||
9A90E18924EAD2BB00471E9A /* GPU.framework */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -713,6 +776,19 @@
|
||||
path = Memory;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9A90E18A24EAD2BB00471E9A /* GPU */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9A90E19524EAD35F00471E9A /* main.swift */,
|
||||
9A90E1A224EAD66600471E9A /* reader.swift */,
|
||||
9A53EBFA24EB041E00648841 /* popup.swift */,
|
||||
9A53EBF824EAFA5200648841 /* settings.swift */,
|
||||
9A90E18C24EAD2BB00471E9A /* Info.plist */,
|
||||
9A90E19724EAD3B000471E9A /* config.plist */,
|
||||
);
|
||||
path = GPU;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9A998CD622A199920087ADE7 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -765,6 +841,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9AABEB65243FCE8A00668CB0 /* CPU */,
|
||||
9A90E18A24EAD2BB00471E9A /* GPU */,
|
||||
9A81C7572449A41400825D92 /* Memory */,
|
||||
9AF9EE0324648751005D2270 /* Disk */,
|
||||
9AE29AD6249A50350071B02D /* Sensors */,
|
||||
@@ -840,6 +917,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9A90E18424EAD2BB00471E9A /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9AABEAD8243FB13500668CB0 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -919,6 +1003,7 @@
|
||||
9A3E17D2247A94AF00449CD1 /* PBXTargetDependency */,
|
||||
9ABFF8FC248BEBCB00C9041A /* PBXTargetDependency */,
|
||||
9AE29ADB249A50350071B02D /* PBXTargetDependency */,
|
||||
9A90E18F24EAD2BB00471E9A /* PBXTargetDependency */,
|
||||
);
|
||||
name = Stats;
|
||||
productName = "Mini Stats";
|
||||
@@ -984,6 +1069,27 @@
|
||||
productReference = 9A81C7562449A41400825D92 /* Memory.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
9A90E18824EAD2BB00471E9A /* GPU */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 9A90E19424EAD2BB00471E9A /* Build configuration list for PBXNativeTarget "GPU" */;
|
||||
buildPhases = (
|
||||
9A90E18424EAD2BB00471E9A /* Headers */,
|
||||
9A90E18524EAD2BB00471E9A /* Sources */,
|
||||
9A90E18624EAD2BB00471E9A /* Frameworks */,
|
||||
9A90E18724EAD2BB00471E9A /* Resources */,
|
||||
9A90E1A124EAD3E300471E9A /* Embed Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
9A90E19C24EAD3E300471E9A /* PBXTargetDependency */,
|
||||
9A90E1A024EAD3E300471E9A /* PBXTargetDependency */,
|
||||
);
|
||||
name = GPU;
|
||||
productName = GPU;
|
||||
productReference = 9A90E18924EAD2BB00471E9A /* GPU.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
9AABEADC243FB13500668CB0 /* ModuleKit */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 9AABEAE8243FB13500668CB0 /* Build configuration list for PBXNativeTarget "ModuleKit" */;
|
||||
@@ -1128,6 +1234,10 @@
|
||||
CreatedOnToolsVersion = 11.4.1;
|
||||
LastSwiftMigration = 1140;
|
||||
};
|
||||
9A90E18824EAD2BB00471E9A = {
|
||||
CreatedOnToolsVersion = 11.6;
|
||||
LastSwiftMigration = 1160;
|
||||
};
|
||||
9AABEADC243FB13500668CB0 = {
|
||||
CreatedOnToolsVersion = 11.4;
|
||||
LastSwiftMigration = 1140;
|
||||
@@ -1172,6 +1282,7 @@
|
||||
9A3E17CB247A94AF00449CD1 /* Net */,
|
||||
9ABFF8F5248BEBCB00C9041A /* Battery */,
|
||||
9AE29AD4249A50350071B02D /* Sensors */,
|
||||
9A90E18824EAD2BB00471E9A /* GPU */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -1216,6 +1327,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9A90E18724EAD2BB00471E9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9A90E19824EAD3B000471E9A /* config.plist in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9AABEADB243FB13500668CB0 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -1316,6 +1435,17 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9A90E18524EAD2BB00471E9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9A90E1A324EAD66600471E9A /* reader.swift in Sources */,
|
||||
9A90E19624EAD35F00471E9A /* main.swift in Sources */,
|
||||
9A53EBFB24EB041E00648841 /* popup.swift in Sources */,
|
||||
9A53EBF924EAFA5200648841 /* settings.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
9AABEAD9243FB13500668CB0 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -1434,6 +1564,21 @@
|
||||
target = 9A0C82D924460F7200FAE3D4 /* StatsKit */;
|
||||
targetProxy = 9A81C76D2449AE9400825D92 /* PBXContainerItemProxy */;
|
||||
};
|
||||
9A90E18F24EAD2BB00471E9A /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 9A90E18824EAD2BB00471E9A /* GPU */;
|
||||
targetProxy = 9A90E18E24EAD2BB00471E9A /* PBXContainerItemProxy */;
|
||||
};
|
||||
9A90E19C24EAD3E300471E9A /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 9AABEADC243FB13500668CB0 /* ModuleKit */;
|
||||
targetProxy = 9A90E19B24EAD3E300471E9A /* PBXContainerItemProxy */;
|
||||
};
|
||||
9A90E1A024EAD3E300471E9A /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 9A0C82D924460F7200FAE3D4 /* StatsKit */;
|
||||
targetProxy = 9A90E19F24EAD3E300471E9A /* PBXContainerItemProxy */;
|
||||
};
|
||||
9AABEAE3243FB13500668CB0 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 9AABEADC243FB13500668CB0 /* ModuleKit */;
|
||||
@@ -1928,6 +2073,69 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
9A90E19224EAD2BB00471E9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = RP2S87B72W;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Modules/GPU/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = eu.exelban.Stats.GPU;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
9A90E19324EAD2BB00471E9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEFINES_MODULE = YES;
|
||||
DEVELOPMENT_TEAM = RP2S87B72W;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Modules/GPU/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = eu.exelban.Stats.GPU;
|
||||
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
9AABEAE6243FB13500668CB0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -2315,6 +2523,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
9A90E19424EAD2BB00471E9A /* Build configuration list for PBXNativeTarget "GPU" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
9A90E19224EAD2BB00471E9A /* Debug */,
|
||||
9A90E19324EAD2BB00471E9A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
9AABEAE8243FB13500668CB0 /* Build configuration list for PBXNativeTarget "ModuleKit" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -16,12 +16,21 @@ import Disk
|
||||
import Net
|
||||
import Battery
|
||||
import Sensors
|
||||
import GPU
|
||||
|
||||
var store: Store = Store()
|
||||
let updater = macAppUpdater(user: "exelban", repo: "stats")
|
||||
let systemKit: SystemKit = SystemKit()
|
||||
var smc: SMCService = SMCService()
|
||||
var modules: [Module] = [Battery(&store), Network(&store), Sensors(&store, &smc), Disk(&store), Memory(&store), CPU(&store, &smc)].reversed()
|
||||
var modules: [Module] = [
|
||||
Battery(&store),
|
||||
Network(&store),
|
||||
Sensors(&store, &smc),
|
||||
Disk(&store),
|
||||
Memory(&store),
|
||||
GPU(&store, &smc),
|
||||
CPU(&store, &smc)
|
||||
].reversed()
|
||||
var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Stats")
|
||||
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {
|
||||
|
||||
@@ -382,4 +382,5 @@ let osDict: [Int: String] = [
|
||||
13: "High Sierra",
|
||||
14: "Mojave",
|
||||
15: "Catalina",
|
||||
16: "Big Sur",
|
||||
]
|
||||
|
||||
@@ -876,6 +876,26 @@ public func getIOParent(_ obj: io_registry_entry_t) -> io_registry_entry_t? {
|
||||
return parent
|
||||
}
|
||||
|
||||
public func fetchIOService(_ name: String) -> [NSDictionary]? {
|
||||
var iterator: io_iterator_t = io_iterator_t()
|
||||
var obj: io_registry_entry_t = 1
|
||||
var list: [NSDictionary] = []
|
||||
|
||||
let result = IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(name), &iterator)
|
||||
if result == kIOReturnSuccess {
|
||||
while obj != 0 {
|
||||
obj = IOIteratorNext(iterator)
|
||||
if let props = getIOProperties(obj) {
|
||||
list.append(props)
|
||||
}
|
||||
IOObjectRelease(obj)
|
||||
}
|
||||
IOObjectRelease(iterator)
|
||||
}
|
||||
|
||||
return list.isEmpty ? nil : list
|
||||
}
|
||||
|
||||
public func getIOProperties(_ entry: io_registry_entry_t) -> NSDictionary? {
|
||||
var properties: Unmanaged<CFMutableDictionary>? = nil
|
||||
|
||||
|
||||
Reference in New Issue
Block a user