- update structure name in modules

- add arguments support (--reset, --disable)
- update a README
This commit is contained in:
Serhiy Mytrovtsiy
2020-06-28 22:31:40 +02:00
parent 8669bb0c2b
commit 3f8ee3bd65
17 changed files with 107 additions and 60 deletions

View File

@@ -17,7 +17,9 @@ public protocol Module_p {
var widget: Widget_p? { get }
var settings: Settings_p? { get }
func load()
func mount()
func unmount()
func terminate()
}
@@ -112,18 +114,18 @@ open class Module: Module_p {
}
// load function which call when app start
public func load() {
if self.enabled && self.widget != nil && self.ready {
DispatchQueue.main.async {
self.menuBarItem.button?.target = self
self.menuBarItem.button?.action = #selector(self.togglePopup)
self.menuBarItem.button?.sendAction(on: [.leftMouseDown, .rightMouseDown])
self.menuBarItem.length = self.widget!.frame.width
self.menuBarItem.button?.addSubview(self.widget!)
self.widgetLoaded = true
}
public func mount() {
guard self.enabled else {
return
}
self.readers.forEach{ $0.start() }
}
// disable module
public func unmount() {
self.enabled = false
self.available = false
}
// terminate function which call before app termination
@@ -147,7 +149,7 @@ open class Module: Module_p {
self.readers.forEach{ $0.start() }
self.menuBarItem.isVisible = true
if self.menuBarItem.length < 0 {
self.load()
self.loadWidget()
}
os_log(.debug, log: log, "Module enabled")
}
@@ -173,20 +175,17 @@ open class Module: Module_p {
// add reader to module. If module is enabled will fire a read function and start a reader
public func addReader(_ reader: Reader_p) {
if self.enabled {
reader.start()
}
self.readers.append(reader)
os_log(.debug, log: log, "Successfully add reader %s", "\(reader.self)")
os_log(.debug, log: log, "Reader %s was added", "\(reader.self)")
}
// handler for reader, calls when main reader is ready, and return first value
public func readyHandler() {
os_log(.debug, log: log, "Reader report readiness")
self.ready = true
if !self.widgetLoaded {
self.load()
self.loadWidget()
}
}
@@ -199,6 +198,21 @@ open class Module: Module_p {
// determine if module is available (can be overrided in module)
open func isAvailable() -> Bool { return true }
// setup menu ber item
private func loadWidget() {
if self.widget != nil && self.ready {
DispatchQueue.main.async {
self.menuBarItem.button?.target = self
self.menuBarItem.button?.action = #selector(self.togglePopup)
self.menuBarItem.button?.sendAction(on: [.leftMouseDown, .rightMouseDown])
self.menuBarItem.length = self.widget!.frame.width
self.menuBarItem.button?.addSubview(self.widget!)
self.widgetLoaded = true
}
}
}
// load and setup widget
private func setWidget() {
self.widget = LoadWidget(self.activeWidget, preview: false, title: self.config.name, config: self.config.widgetsConfig, store: self.store)

View File

@@ -69,8 +69,10 @@ open class Reader<T>: ReaderInternal_p {
public func callback(_ value: T?) {
if !self.optional && !self.ready {
if self.value == nil && value != nil {
self.ready = true
self.readyCallback()
} else if self.value == nil && value == nil {
os_log(.debug, log: self.log, "Reader is ready")
} else if self.value == nil && value != nil {
if self.nilCallbackCounter > 5 {
os_log(.error, log: self.log, "Callback receive nil value more than 5 times. Please check this reader!")
self.stop()
@@ -87,10 +89,6 @@ open class Reader<T>: ReaderInternal_p {
}
self.value = value
if !self.ready {
self.ready = true
os_log(.debug, log: self.log, "Reader is ready")
}
if value != nil {
if self.history?.count ?? 0 >= 300 {
self.history!.remove(at: 0)

View File

@@ -14,7 +14,7 @@ import StatsKit
import ModuleKit
import IOKit.ps
struct Usage: value_t {
struct Battery_Usage: value_t {
var powerSource: String = ""
var state: String = ""
var isCharged: Bool = false
@@ -66,7 +66,7 @@ public class Battery: Module {
return sources.count > 0
}
private func usageCallback(_ value: Usage?) {
private func usageCallback(_ value: Battery_Usage?) {
if value == nil {
return
}

View File

@@ -127,7 +127,7 @@ internal class Popup: NSView {
self.adapterView = view
}
public func usageCallback(_ value: Usage) {
public func usageCallback(_ value: Battery_Usage) {
DispatchQueue.main.async(execute: {
self.dashboardBatteryView?.setValue(abs(value.level))

View File

@@ -12,13 +12,13 @@
import Cocoa
import ModuleKit
internal class UsageReader: Reader<Usage> {
internal class UsageReader: Reader<Battery_Usage> {
private var service: io_connect_t = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleSmartBattery"))
private var source: CFRunLoopSource?
private var loop: CFRunLoop?
private var usage: Usage = Usage()
private var usage: Battery_Usage = Battery_Usage()
public override func start() {
let context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())

View File

@@ -10,7 +10,7 @@ import Cocoa
import ModuleKit
import StatsKit
public struct Load: value_t {
public struct CPU_Load: value_t {
var totalUsage: Double = 0
var usagePerCore: [Double] = []
@@ -35,13 +35,13 @@ public class CPU: Module {
private let popupView: Popup = Popup()
private var settingsView: Settings
private var loadReader: LoadReader = LoadReader()
private var loadReader: LoadReader? = LoadReader()
private let smc: UnsafePointer<SMCService>?
public init(_ store: UnsafePointer<Store>, _ smc: UnsafePointer<SMCService>) {
self.smc = smc
self.settingsView = Settings("CPU", store: store)
self.loadReader.store = store
self.loadReader!.store = store
super.init(
store: store,
@@ -50,20 +50,20 @@ public class CPU: Module {
)
self.settingsView.callback = { [unowned self] in
self.loadReader.read()
self.loadReader?.read()
}
self.loadReader.readyCallback = { [unowned self] in
self.loadReader?.readyCallback = { [unowned self] in
self.readyHandler()
}
self.loadReader.callbackHandler = { [unowned self] value in
self.loadReader?.callbackHandler = { [unowned self] value in
self.loadCallback(value)
}
self.addReader(self.loadReader)
self.addReader(self.loadReader!)
}
private func loadCallback(_ value: Load?) {
private func loadCallback(_ value: CPU_Load?) {
if value == nil {
return
}

View File

@@ -95,7 +95,7 @@ internal class Popup: NSView {
return valueView
}
public func loadCallback(_ value: Load, tempValue: Double?) {
public func loadCallback(_ value: CPU_Load, tempValue: Double?) {
var temperature: String = "Unknown"
DispatchQueue.main.async(execute: {

View File

@@ -13,7 +13,7 @@ import Cocoa
import StatsKit
import ModuleKit
internal class LoadReader: Reader<Load> {
internal class LoadReader: Reader<CPU_Load> {
public var store: UnsafePointer<Store>? = nil
private var cpuInfo: processor_info_array_t!
@@ -24,7 +24,7 @@ internal class LoadReader: Reader<Load> {
private let CPUUsageLock: NSLock = NSLock()
private var previousInfo = host_cpu_load_info()
private var response: Load = Load()
private var response: CPU_Load = CPU_Load()
private var numCPUsU: natural_t = 0
private var usagePerCore: [Double] = []

View File

@@ -13,7 +13,7 @@ import Cocoa
import StatsKit
import ModuleKit
public struct Usage: value_t {
public struct RAM_Usage: value_t {
var active: Double?
var inactive: Double?
var wired: Double?
@@ -52,7 +52,7 @@ public class Memory: Module {
self.addReader(self.usageReader)
}
private func loadCallback(value: Usage?) {
private func loadCallback(value: RAM_Usage?) {
if value == nil {
return
}

View File

@@ -99,7 +99,7 @@ internal class Popup: NSView {
return valueView
}
public func loadCallback(_ value: Usage) {
public func loadCallback(_ value: RAM_Usage) {
DispatchQueue.main.async(execute: {
if self.window!.isVisible || !self.initialized {
self.activeField?.stringValue = Units(bytes: Int64(value.active!)).getReadableMemory()

View File

@@ -12,7 +12,7 @@
import Cocoa
import ModuleKit
internal class UsageReader: Reader<Usage> {
internal class UsageReader: Reader<RAM_Usage> {
public var totalSize: Double = 0
public override func setup() {
@@ -53,7 +53,7 @@ internal class UsageReader: Reader<Usage> {
let used = active + wired + compressed
let free = self.totalSize - used
self.callback(Usage(
self.callback(RAM_Usage(
active: active,
inactive: inactive,
wired: wired,

View File

@@ -18,7 +18,7 @@ public enum Network_t: String {
case ethernet
}
public struct Usage: value_t {
public struct Network_Usage: value_t {
var active: Bool = false
var download: Int64 = 0
@@ -73,7 +73,7 @@ public class Network: Module {
self.addReader(self.usageReader)
}
private func usageCallback(_ value: Usage?) {
private func usageCallback(_ value: Network_Usage?) {
if value == nil {
return
}

View File

@@ -145,7 +145,7 @@ internal class Popup: NSView {
self.addSubview(view)
}
public func usageCallback(_ value: Usage) {
public func usageCallback(_ value: Network_Usage) {
DispatchQueue.main.async(execute: {
if !self.window!.isVisible && self.initialized && value.active {
return

View File

@@ -16,9 +16,9 @@ import Reachability
import os.log
import CoreWLAN
internal class UsageReader: Reader<Usage> {
internal class UsageReader: Reader<Network_Usage> {
private var reachability: Reachability? = nil
private var usage: Usage = Usage()
private var usage: Network_Usage = Network_Usage()
private var interfaceID: String? = nil

View File

@@ -1,6 +1,6 @@
# Stats
<p align="center"><img src="https://serhiy.s3.eu-central-1.amazonaws.com/Github_repo/stats/logo.png?raw=true" width="120"></p>
<a href="https://github.com/exelban/stats/releases"><p align="center"><img src="https://serhiy.s3.eu-central-1.amazonaws.com/Github_repo/stats/logo.png?raw=true" width="120"></p></a>
[![Stats](https://serhiy.s3.eu-central-1.amazonaws.com/Github_repo/stats/cover%3Fv1.6.0.png)](https://github.com/exelban/stats/releases)
@@ -25,14 +25,23 @@ Stats is a application which allows you to monitor your macOS system.
- CPU Usage
- Memory Usage
- Disk utilization
- Sensors information (Temperature/Voltage/Power)
- Battery level
- Network usage
## Troubleshoots
The application supports a few arguments which can help to work with Stats. Also, it's very helpful to debug what module is not working properly (crash).
There are 2 arguments available:
- `--reset`: allows to reset application settings
- `--disable`: allow to disable some of the modules. A list of modules can be passed. (Example: `--disable disk`)
## Developing
Pull requests and impovment proposals are welcomed.
If you want to run the project locally you need to have [carthage](https://github.com/Carthage/Carthage#installing-carthage) installed.
If you want to run the project locally you need to have [carthage](https://github.com/Carthage/Carthage#installing-carthage) and [XCode](https://apps.apple.com/app/xcode/id497799835) installed.
```bash
git clone https://github.com/exelban/stats

View File

@@ -59,6 +59,16 @@
ReferencedContainer = "container:Stats.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "--reset"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "--disable"
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
<EnvironmentVariables>
<EnvironmentVariable
key = "DYLD_PRINT_STATISTICS"
@@ -71,13 +81,6 @@
isEnabled = "NO">
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions>
<AdditionalOption
key = "MallocStackLogging"
value = ""
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Debug"

View File

@@ -31,10 +31,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
let startingPoint = Date()
self.parseArguments()
NotificationCenter.default.addObserver(self, selector: #selector(toggleSettingsHandler), name: .toggleSettings, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(checkForUpdates), name: .checkForUpdates, object: nil)
modules.forEach{ $0.load() }
modules.forEach{ $0.mount() }
self.settingsWindow.setModules()
@@ -97,6 +99,27 @@ class AppDelegate: NSObject, NSApplicationDelegate {
store.set(key: key, value: currentVersion)
}
private func parseArguments() {
let args = CommandLine.arguments
if args.contains("--reset") {
os_log(.info, log: log, "Receive --reset argument. Reseting store (UserDefaults)...")
store.reset()
}
if let disableIndex = args.firstIndex(of: "--disable") {
if args.indices.contains(disableIndex+1) {
let disableModules = args[disableIndex+1].split(separator: ",")
disableModules.forEach { (moduleName: Substring) in
if let module = modules.first(where: { $0.config.name.lowercased() == moduleName.lowercased()}) {
module.unmount()
}
}
}
}
}
private func defaultValues() {
if !store.exist(key: "runAtLoginInitialized") {
store.set(key: "runAtLoginInitialized", value: true)