diff --git a/Modules/Disk/settings.swift b/Modules/Disk/settings.swift index e07b4c82..d502c8f7 100644 --- a/Modules/Disk/settings.swift +++ b/Modules/Disk/settings.swift @@ -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) diff --git a/Modules/GPU/config.plist b/Modules/GPU/config.plist index 43302fd6..c9c64a7a 100644 --- a/Modules/GPU/config.plist +++ b/Modules/GPU/config.plist @@ -6,5 +6,55 @@ GPU State + Widgets + + mini + + Default + + Preview + + Value + 0.32 + + Unsupported colors + + pressure + + Order + 0 + + line_chart + + Default + + Color + systemAccent + Unsupported colors + + pressure + + Order + 1 + + bar_chart + + Default + + Preview + + Value + 0.36,0.28,0.32,0.26 + Color + + + Unsupported colors + + pressure + + Order + 2 + + diff --git a/Modules/GPU/main.swift b/Modules/GPU/main.swift index c6ab28a2..61e18f7b 100644 --- a/Modules/GPU/main.swift +++ b/Modules/GPU/main.swift @@ -13,33 +13,103 @@ import Cocoa import ModuleKit import StatsKit -public struct GPU_Load {} +public struct GPU_Info { + public let name: String + public let IOclass: String + public var state: Bool = false + + public var utilization: Double = 0 + + public var totalVram: Int = 0 + public var freeVram: Int = 0 + public var coreClock: Int = 0 + public var power: Int = 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? private let store: UnsafePointer - private var loadReader: LoadReader? = nil + private var infoReader: InfoReader? = nil + private var settingsView: Settings + private var popupView: Popup = Popup() + + private var selectedGPU: String = "" public init(_ store: UnsafePointer, _ smc: UnsafePointer) { self.store = store self.smc = smc + self.settingsView = Settings("GPU", store: store) super.init( store: store, - popup: nil, - settings: nil + popup: self.popupView, + settings: self.settingsView ) guard self.available else { return } - self.loadReader = LoadReader() + self.infoReader = InfoReader() + self.infoReader?.smc = smc + self.selectedGPU = store.pointee.string(key: "\(self.config.name)_gpu", defaultValue: self.selectedGPU) - self.loadReader?.readyCallback = { [unowned self] in + self.infoReader?.readyCallback = { [unowned self] in self.readyHandler() } + self.infoReader?.callbackHandler = { [unowned self] value in + self.infoCallback(value) + } - if let reader = self.loadReader { + 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]) + } + } } diff --git a/Modules/GPU/popup.swift b/Modules/GPU/popup.swift new file mode 100644 index 00000000..10d7e8a8 --- /dev/null +++ b/Modules/GPU/popup.swift @@ -0,0 +1,32 @@ +// +// 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 { + 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) { + print(value) + } +} + +private class GPUView: NSView { + +} diff --git a/Modules/GPU/reader.swift b/Modules/GPU/reader.swift index 879b7966..9a3c77cd 100644 --- a/Modules/GPU/reader.swift +++ b/Modules/GPU/reader.swift @@ -14,8 +14,94 @@ import StatsKit import ModuleKit import os.log -internal class LoadReader: Reader { +internal class InfoReader: Reader { + internal var smc: UnsafePointer? = nil + private var gpus: GPUs = GPUs() + public override func read() { + guard let devices = fetchIOService("IOPCIDevice") else { + return + } + let gpus = devices.filter{ $0.object(forKey: "IOName") as? String == "display" } + guard let acceletators = fetchIOService(kIOAcceleratorClassName) else { + return + } + + acceletators.forEach { (accelerator: NSDictionary) in + guard let matchedGPU = gpus.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 + let freeVram = stats["vramFreeBytes"] as? Int ?? 0 + let coreClock = stats["Core Clock(MHz)"] as? Int ?? 0 + var power = stats["Total Power(W)"] 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) + } + } + + if power == 0 { + if let pwr = self.smc?.pointee.getValue("PCPG") { + power = Int(pwr) + } else if let pwr = self.smc?.pointee.getValue("PCGC") { + power = Int(pwr) + } else if let pwr = self.smc?.pointee.getValue("PCGM") { + power = Int(pwr) + } + } + } + + self.gpus.list[idx].state = agcInfo["poweredOffByAGC"] == 0 + + self.gpus.list[idx].utilization = utilization == 0 ? 0 : Double(utilization)/100 + self.gpus.list[idx].totalVram = totalVram + self.gpus.list[idx].freeVram = freeVram + self.gpus.list[idx].coreClock = coreClock + self.gpus.list[idx].power = power + self.gpus.list[idx].temperature = temperature + } + + self.callback(self.gpus) } } diff --git a/Modules/GPU/settings.swift b/Modules/GPU/settings.swift new file mode 100644 index 00000000..4381afbc --- /dev/null +++ b/Modules/GPU/settings.swift @@ -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 + + 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) { + 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) + } +} diff --git a/Modules/Net/settings.swift b/Modules/Net/settings.swift index 6132d7c2..2c4a20a6 100644 --- a/Modules/Net/settings.swift +++ b/Modules/Net/settings.swift @@ -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) diff --git a/Modules/Sensors/values.swift b/Modules/Sensors/values.swift index f84882a7..db418c2c 100644 --- a/Modules/Sensors/values.swift +++ b/Modules/Sensors/values.swift @@ -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), diff --git a/Stats.xcodeproj/project.pbxproj b/Stats.xcodeproj/project.pbxproj index 5b1473d3..1cae54a4 100644 --- a/Stats.xcodeproj/project.pbxproj +++ b/Stats.xcodeproj/project.pbxproj @@ -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 */; }; @@ -462,6 +464,8 @@ 9A3E17E9247B07BF00449CD1 /* popup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = popup.swift; sourceTree = ""; }; 9A41530B24ABC3AF00A2BDA7 /* Memory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Memory.swift; sourceTree = ""; }; 9A5349CD23D8832E00C23824 /* Reachability.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Reachability.framework; path = Carthage/Build/Mac/Reachability.framework; sourceTree = ""; }; + 9A53EBF824EAFA5200648841 /* settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = settings.swift; sourceTree = ""; }; + 9A53EBFA24EB041E00648841 /* popup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = popup.swift; sourceTree = ""; }; 9A58DE9D24B363D800716A9F /* popup.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = popup.swift; sourceTree = ""; }; 9A58DE9F24B363F300716A9F /* settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = settings.swift; sourceTree = ""; }; 9A58DEA324B3647600716A9F /* settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = settings.swift; sourceTree = ""; }; @@ -777,6 +781,8 @@ children = ( 9A90E19524EAD35F00471E9A /* main.swift */, 9A90E1A224EAD66600471E9A /* reader.swift */, + 9A53EBF824EAFA5200648841 /* settings.swift */, + 9A53EBFA24EB041E00648841 /* popup.swift */, 9A90E18C24EAD2BB00471E9A /* Info.plist */, 9A90E19724EAD3B000471E9A /* config.plist */, ); @@ -1435,6 +1441,8 @@ files = ( 9A90E1A324EAD66600471E9A /* reader.swift in Sources */, 9A90E19624EAD35F00471E9A /* main.swift in Sources */, + 9A53EBFB24EB041E00648841 /* popup.swift in Sources */, + 9A53EBF924EAFA5200648841 /* settings.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/StatsKit/SystemKit.swift b/StatsKit/SystemKit.swift index dcc18f9b..7b4fd03c 100644 --- a/StatsKit/SystemKit.swift +++ b/StatsKit/SystemKit.swift @@ -382,4 +382,5 @@ let osDict: [Int: String] = [ 13: "High Sierra", 14: "Mojave", 15: "Catalina", + 16: "Big Sur", ] diff --git a/StatsKit/extensions.swift b/StatsKit/extensions.swift index f2716b1d..94a8a8b8 100644 --- a/StatsKit/extensions.swift +++ b/StatsKit/extensions.swift @@ -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? = nil