This commit is contained in:
JoniVR 2018-12-16 16:29:21 +01:00
parent 53e168c319
commit 79bd48166e
2 changed files with 223 additions and 287 deletions

View file

@ -7,13 +7,13 @@
objects = {
/* Begin PBXBuildFile section */
2E3C2647A29DDCAA1F2D4E29 /* Pods_MonitorControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65A9B356B917FAB6583F09A6 /* Pods_MonitorControl.framework */; };
56754EAF1D9A4016007BCDC5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */; };
56754EB11D9A4016007BCDC5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 56754EB01D9A4016007BCDC5 /* Assets.xcassets */; };
56754EB41D9A4016007BCDC5 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 56754EB21D9A4016007BCDC5 /* MainMenu.xib */; };
6C33119021C58BF600971151 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 6C33118921C58BF500971151 /* README.md */; };
6C33119221C58BF600971151 /* ddcctl.sh in Resources */ = {isa = PBXBuildFile; fileRef = 6C33118C21C58BF500971151 /* ddcctl.sh */; };
6C33119521C58BF600971151 /* DDC.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C33118F21C58BF600971151 /* DDC.c */; };
9A19D3B73485870616B6D4E0 /* Pods_MonitorControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 398F482D5C8816B29F16AAEB /* Pods_MonitorControl.framework */; };
F03A8DF21FFBAA6F0034DC27 /* Display.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03A8DF11FFBAA6F0034DC27 /* Display.swift */; };
F0445D3820023E710025AE82 /* MainPrefsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0445D3720023E710025AE82 /* MainPrefsViewController.swift */; };
F0445D3D200254FA0025AE82 /* KeysPrefsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0445D3B200254FA0025AE82 /* KeysPrefsViewController.swift */; };
@ -44,13 +44,13 @@
/* Begin PBXFileReference section */
31E16D90527EBD3F8A12BE0B /* Pods-MonitorControl.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MonitorControl.release.xcconfig"; path = "Pods/Target Support Files/Pods-MonitorControl/Pods-MonitorControl.release.xcconfig"; sourceTree = "<group>"; };
398F482D5C8816B29F16AAEB /* Pods_MonitorControl.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MonitorControl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
42B61ABC1D7907131330228A /* Pods-MonitorControl.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MonitorControl.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MonitorControl/Pods-MonitorControl.debug.xcconfig"; sourceTree = "<group>"; };
56754EAB1D9A4016007BCDC5 /* MonitorControl.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MonitorControl.app; sourceTree = BUILT_PRODUCTS_DIR; };
56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AppDelegate.swift; sourceTree = "<group>"; };
56754EB01D9A4016007BCDC5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
56754EB31D9A4016007BCDC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
56754EB51D9A4016007BCDC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
65A9B356B917FAB6583F09A6 /* Pods_MonitorControl.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MonitorControl.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6C33118921C58BF500971151 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
6C33118B21C58BF500971151 /* DDC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDC.h; sourceTree = "<group>"; };
6C33118C21C58BF500971151 /* ddcctl.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ddcctl.sh; sourceTree = "<group>"; };
@ -77,17 +77,6 @@
F091C9C31F6EB8720096FD65 /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
F091C9C41F6EBA5A0096FD65 /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
F0A987D61F77B290009B603D /* OSD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OSD.framework; sourceTree = "<group>"; };
F0A987DA1F77B404009B603D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/MainMenu.strings; sourceTree = "<group>"; };
F0A987DC1F77B404009B603D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
F0A987DD1F77B404009B603D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
F0A987DF1F77B404009B603D /* SliderHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderHandler.swift; sourceTree = "<group>"; };
F0A987E11F77B404009B603D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
F0A987E21F77B404009B603D /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
F0A987E31F77B404009B603D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/MainMenu.strings; sourceTree = "<group>"; };
F0A987E41F77B404009B603D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
F0A987E51F77B404009B603D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
F0A987E61F77B404009B603D /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
F0A987E71F77B404009B603D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -96,7 +85,7 @@
buildActionMask = 2147483647;
files = (
F0A987E81F77B40E009B603D /* OSD.framework in Frameworks */,
9A19D3B73485870616B6D4E0 /* Pods_MonitorControl.framework in Frameworks */,
2E3C2647A29DDCAA1F2D4E29 /* Pods_MonitorControl.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -131,8 +120,8 @@
55359E321E2737EC002671BC /* ddcctl */,
F06792E8200A73460066C438 /* MonitorControlHelper */,
56754EAC1D9A4016007BCDC5 /* Products */,
F0A987D71F77B404009B603D /* Frameworks */,
EFFC2F3E35BEC9ACFA754137 /* Pods */,
8ABFD04A9742F18299723076 /* Frameworks */,
);
sourceTree = "<group>";
};
@ -162,6 +151,14 @@
path = MonitorControl;
sourceTree = "<group>";
};
8ABFD04A9742F18299723076 /* Frameworks */ = {
isa = PBXGroup;
children = (
65A9B356B917FAB6583F09A6 /* Pods_MonitorControl.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
EFFC2F3E35BEC9ACFA754137 /* Pods */ = {
isa = PBXGroup;
children = (
@ -201,39 +198,6 @@
path = Objects;
sourceTree = "<group>";
};
F0A987D71F77B404009B603D /* Frameworks */ = {
isa = PBXGroup;
children = (
F0A987D81F77B404009B603D /* MonitorControl */,
398F482D5C8816B29F16AAEB /* Pods_MonitorControl.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
F0A987D81F77B404009B603D /* MonitorControl */ = {
isa = PBXGroup;
children = (
F0A987D91F77B404009B603D /* MainMenu.strings */,
F0A987DB1F77B404009B603D /* Localizable.strings */,
F0A987DD1F77B404009B603D /* Assets.xcassets */,
F0A987DE1F77B404009B603D /* Objects */,
F0A987E01F77B404009B603D /* MainMenu.xib */,
F0A987E21F77B404009B603D /* Utils.swift */,
F0A987E51F77B404009B603D /* AppDelegate.swift */,
F0A987E61F77B404009B603D /* Bridging-Header.h */,
F0A987E71F77B404009B603D /* Info.plist */,
);
path = MonitorControl;
sourceTree = "<group>";
};
F0A987DE1F77B404009B603D /* Objects */ = {
isa = PBXGroup;
children = (
F0A987DF1F77B404009B603D /* SliderHandler.swift */,
);
path = Objects;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -439,32 +403,6 @@
name = Localizable.strings;
sourceTree = "<group>";
};
F0A987D91F77B404009B603D /* MainMenu.strings */ = {
isa = PBXVariantGroup;
children = (
F0A987DA1F77B404009B603D /* en */,
F0A987E31F77B404009B603D /* fr */,
);
name = MainMenu.strings;
sourceTree = "<group>";
};
F0A987DB1F77B404009B603D /* Localizable.strings */ = {
isa = PBXVariantGroup;
children = (
F0A987DC1F77B404009B603D /* en */,
F0A987E41F77B404009B603D /* fr */,
);
name = Localizable.strings;
sourceTree = "<group>";
};
F0A987E01F77B404009B603D /* MainMenu.xib */ = {
isa = PBXVariantGroup;
children = (
F0A987E11F77B404009B603D /* Base */,
);
name = MainMenu.xib;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */

View file

@ -16,133 +16,129 @@ var app: AppDelegate! = nil
let prefs = UserDefaults.standard
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate {
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var statusMenu: NSMenu!
@IBOutlet weak var window: NSWindow!
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
var monitorItems: [NSMenuItem] = []
var displays: [Display] = []
let step = 100/16
var mediaKeyTap: MediaKeyTap?
var prefsController: NSWindowController?
var keysListenedFor: [MediaKey] = [.brightnessUp, .brightnessDown, .mute, .volumeUp, .volumeDown]
let step = 100/16
var mediaKeyTap: MediaKeyTap?
var prefsController: NSWindowController?
var keysListenedFor: [MediaKey] = [.brightnessUp, .brightnessDown, .mute, .volumeUp, .volumeDown]
func applicationDidFinishLaunching(_ aNotification: Notification) {
app = self
let listenFor = prefs.integer(forKey: Utils.PrefKeys.listenFor.rawValue)
if listenFor == Utils.ListenForKeys.brightnessOnlyKeys.rawValue {
keysListenedFor.removeSubrange(2...4)
} else if listenFor == Utils.ListenForKeys.volumeOnlyKeys.rawValue {
keysListenedFor.removeSubrange(0...1)
}
mediaKeyTap = MediaKeyTap.init(delegate: self, for: keysListenedFor, observeBuiltIn: false)
let storyboard: NSStoryboard = NSStoryboard.init(name: "Main", bundle: Bundle.main)
let views = [
storyboard.instantiateController(withIdentifier: "MainPrefsVC"),
storyboard.instantiateController(withIdentifier: "KeysPrefsVC"),
storyboard.instantiateController(withIdentifier: "DisplayPrefsVC")
]
prefsController = MASPreferencesWindowController(viewControllers: views, title: NSLocalizedString("Preferences", comment: "Shown in Preferences window"))
NotificationCenter.default.addObserver(self, selector: #selector(handleListenForChanged), name: NSNotification.Name.init(Utils.PrefKeys.listenFor.rawValue), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleShowContrastChanged), name: NSNotification.Name.init(Utils.PrefKeys.showContrast.rawValue), object: nil)
statusItem.image = NSImage.init(named: "status")
let listenFor = prefs.integer(forKey: Utils.PrefKeys.listenFor.rawValue)
if listenFor == Utils.ListenForKeys.brightnessOnlyKeys.rawValue {
keysListenedFor.removeSubrange(2...4)
} else if listenFor == Utils.ListenForKeys.volumeOnlyKeys.rawValue {
keysListenedFor.removeSubrange(0...1)
}
mediaKeyTap = MediaKeyTap.init(delegate: self, for: keysListenedFor, observeBuiltIn: false)
let storyboard: NSStoryboard = NSStoryboard.init(name: "Main", bundle: Bundle.main)
let views = [
storyboard.instantiateController(withIdentifier: "MainPrefsVC"),
storyboard.instantiateController(withIdentifier: "KeysPrefsVC"),
storyboard.instantiateController(withIdentifier: "DisplayPrefsVC")
]
prefsController = MASPreferencesWindowController(viewControllers: views, title: NSLocalizedString("Preferences", comment: "Shown in Preferences window"))
NotificationCenter.default.addObserver(self, selector: #selector(handleListenForChanged), name: NSNotification.Name.init(Utils.PrefKeys.listenFor.rawValue), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleShowContrastChanged), name: NSNotification.Name.init(Utils.PrefKeys.showContrast.rawValue), object: nil)
statusItem.image = NSImage.init(named: "status")
statusItem.menu = statusMenu
setDefaultPrefs()
setDefaultPrefs()
Utils.acquirePrivileges()
CGDisplayRegisterReconfigurationCallback({_, _, _ in app.updateDisplays()}, nil)
updateDisplays()
mediaKeyTap?.start()
mediaKeyTap?.start()
}
func applicationWillTerminate(_ aNotification: Notification) {
}
@IBAction func quitClicked(_ sender: AnyObject) {
NSApplication.shared.terminate(self)
}
@IBAction func prefsClicked(_ sender: AnyObject) {
if let prefsController = prefsController {
prefsController.showWindow(sender)
NSApp.activate(ignoringOtherApps: true)
prefsController.window?.makeKeyAndOrderFront(sender)
}
}
/// Set the default prefs of the app
func setDefaultPrefs() {
let prefs = UserDefaults.standard
if !prefs.bool(forKey: Utils.PrefKeys.appAlreadyLaunched.rawValue) {
prefs.set(true, forKey: Utils.PrefKeys.appAlreadyLaunched.rawValue)
prefs.set(false, forKey: Utils.PrefKeys.startAtLogin.rawValue)
prefs.set(false, forKey: Utils.PrefKeys.showContrast.rawValue)
prefs.set(false, forKey: Utils.PrefKeys.lowerContrast.rawValue)
}
}
// MARK: - Menu
func clearDisplays() {
if statusMenu.items.count > 2 {
var items: [NSMenuItem] = []
for i in 0..<statusMenu.items.count - 2 {
items.append(statusMenu.items[i])
}
for item in items {
statusMenu.removeItem(item)
}
}
monitorItems = []
displays = []
}
@IBAction func quitClicked(_ sender: AnyObject) {
NSApplication.shared.terminate(self)
}
@IBAction func prefsClicked(_ sender: AnyObject) {
if let prefsController = prefsController {
prefsController.showWindow(sender)
NSApp.activate(ignoringOtherApps: true)
prefsController.window?.makeKeyAndOrderFront(sender)
}
}
/// Set the default prefs of the app
func setDefaultPrefs() {
let prefs = UserDefaults.standard
if !prefs.bool(forKey: Utils.PrefKeys.appAlreadyLaunched.rawValue) {
prefs.set(true, forKey: Utils.PrefKeys.appAlreadyLaunched.rawValue)
prefs.set(false, forKey: Utils.PrefKeys.startAtLogin.rawValue)
prefs.set(false, forKey: Utils.PrefKeys.showContrast.rawValue)
prefs.set(false, forKey: Utils.PrefKeys.lowerContrast.rawValue)
}
}
// MARK: - Menu
func clearDisplays() {
if statusMenu.items.count > 2 {
var items: [NSMenuItem] = []
for i in 0..<statusMenu.items.count - 2 {
items.append(statusMenu.items[i])
}
for item in items {
statusMenu.removeItem(item)
}
}
monitorItems = []
displays = []
}
func updateDisplays() {
clearDisplays()
var filteredScreens = NSScreen.screens.filter { screen -> Bool in
if let id = screen.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as? CGDirectDisplayID {
// Is Built In Screen (e.g. MBP/iMac Screen)
if CGDisplayIsBuiltin(id) != 0 {
return false
}
// Does screen support EDID ?
var edid = EDID()
if !EDIDTest(id, &edid) {
return false
}
return true
}
return false
}
if filteredScreens.count == 1 {
self.addScreenToMenu(screen: filteredScreens[0], asSubMenu: false)
} else {
for screen in filteredScreens {
self.addScreenToMenu(screen: screen, asSubMenu: true)
}
}
clearDisplays()
var filteredScreens = NSScreen.screens.filter { screen -> Bool in
if let id = screen.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as? CGDirectDisplayID {
// Is Built In Screen (e.g. MBP/iMac Screen)
if CGDisplayIsBuiltin(id) != 0 {
return false
}
// Does screen support EDID ?
var edid = EDID()
if !EDIDTest(id, &edid) {
return false
}
return true
}
return false
}
if filteredScreens.count == 1 {
self.addScreenToMenu(screen: filteredScreens[0], asSubMenu: false)
} else {
for screen in filteredScreens {
self.addScreenToMenu(screen: screen, asSubMenu: true)
}
}
if filteredScreens.count == 0 {
// If no DDC capable display was detected
let item = NSMenuItem()
@ -152,103 +148,105 @@ class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate {
statusMenu.insertItem(item, at: 0)
}
}
/// Add a screen to the menu
///
/// - Parameters:
/// - screen: The screen to add
/// - asSubMenu: Display in a sub menu or directly in menu
private func addScreenToMenu(screen: NSScreen, asSubMenu: Bool) {
if let id = screen.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as? CGDirectDisplayID {
var edid = EDID()
if EDIDTest(id, &edid) {
let name = Utils.getDisplayName(forEdid: edid)
let serial = Utils.getDisplaySerial(forEdid: edid)
let display = Display.init(id, name: name, serial: serial)
let monitorSubMenu: NSMenu = asSubMenu ? NSMenu() : statusMenu
let volumeSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu,
forDisplay: display,
command: AUDIO_SPEAKER_VOLUME,
title: NSLocalizedString("Volume", comment: "Shown in menu"))
let brightnessSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu,
forDisplay: display,
command: BRIGHTNESS,
title: NSLocalizedString("Brightness", comment: "Shown in menu"))
if prefs.bool(forKey: Utils.PrefKeys.showContrast.rawValue) {
let contrastSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu,
forDisplay: display,
command: CONTRAST,
title: NSLocalizedString("Contrast", comment: "Shown in menu"))
display.contrastSliderHandler = contrastSliderHandler
}
display.volumeSliderHandler = volumeSliderHandler
display.brightnessSliderHandler = brightnessSliderHandler
displays.append(display)
let monitorMenuItem = NSMenuItem()
monitorMenuItem.title = "\(name)"
if asSubMenu {
monitorMenuItem.submenu = monitorSubMenu
}
monitorItems.append(monitorMenuItem)
statusMenu.insertItem(monitorMenuItem, at: 0)
}
}
}
// MARK: - Media Key Tap delegate
func handle(mediaKey: MediaKey, event: KeyEvent?) {
guard let currentDisplay = Utils.getCurrentDisplay(from: displays) else { return }
let allDisplays = prefs.bool(forKey: Utils.PrefKeys.allScreens.rawValue) ? displays : [currentDisplay]
for display in allDisplays {
if (prefs.object(forKey: "\(display.identifier)-state") as? Bool) ?? true {
switch mediaKey {
case .brightnessUp:
let value = display.calcNewValue(for: BRIGHTNESS, withRel: +step)
display.setBrightness(to: value)
case .brightnessDown:
let value = currentDisplay.calcNewValue(for: BRIGHTNESS, withRel: -step)
display.setBrightness(to: value)
case .mute:
display.mute()
case .volumeUp:
let value = display.calcNewValue(for: AUDIO_SPEAKER_VOLUME, withRel: +step)
display.setVolume(to: value)
case .volumeDown:
let value = display.calcNewValue(for: AUDIO_SPEAKER_VOLUME, withRel: -step)
display.setVolume(to: value)
default:
return
}
}
}
}
// MARK: - Prefs notification
@objc func handleListenForChanged() {
let listenFor = prefs.integer(forKey: Utils.PrefKeys.listenFor.rawValue)
keysListenedFor = [.brightnessUp, .brightnessDown, .mute, .volumeUp, .volumeDown]
if listenFor == Utils.ListenForKeys.brightnessOnlyKeys.rawValue {
keysListenedFor.removeSubrange(2...4)
} else if listenFor == Utils.ListenForKeys.volumeOnlyKeys.rawValue {
keysListenedFor.removeSubrange(0...1)
}
mediaKeyTap?.stop()
mediaKeyTap = MediaKeyTap.init(delegate: self, for: keysListenedFor, observeBuiltIn: false)
mediaKeyTap?.start()
}
@objc func handleShowContrastChanged() {
self.updateDisplays()
}
/// Add a screen to the menu
///
/// - Parameters:
/// - screen: The screen to add
/// - asSubMenu: Display in a sub menu or directly in menu
private func addScreenToMenu(screen: NSScreen, asSubMenu: Bool) {
if let id = screen.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as? CGDirectDisplayID {
var edid = EDID()
if EDIDTest(id, &edid) {
let name = Utils.getDisplayName(forEdid: edid)
let serial = Utils.getDisplaySerial(forEdid: edid)
let display = Display.init(id, name: name, serial: serial)
let monitorSubMenu: NSMenu = asSubMenu ? NSMenu() : statusMenu
let volumeSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu,
forDisplay: display,
command: AUDIO_SPEAKER_VOLUME,
title: NSLocalizedString("Volume", comment: "Shown in menu"))
let brightnessSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu,
forDisplay: display,
command: BRIGHTNESS,
title: NSLocalizedString("Brightness", comment: "Shown in menu"))
if prefs.bool(forKey: Utils.PrefKeys.showContrast.rawValue) {
let contrastSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu,
forDisplay: display,
command: CONTRAST,
title: NSLocalizedString("Contrast", comment: "Shown in menu"))
display.contrastSliderHandler = contrastSliderHandler
}
display.volumeSliderHandler = volumeSliderHandler
display.brightnessSliderHandler = brightnessSliderHandler
displays.append(display)
let monitorMenuItem = NSMenuItem()
monitorMenuItem.title = "\(name)"
if asSubMenu {
monitorMenuItem.submenu = monitorSubMenu
}
monitorItems.append(monitorMenuItem)
statusMenu.insertItem(monitorMenuItem, at: 0)
}
}
}
}
// MARK: - Media Key Tap delegate
extension AppDelegate: MediaKeyTapDelegate {
func handle(mediaKey: MediaKey, event: KeyEvent?) {
guard let currentDisplay = Utils.getCurrentDisplay(from: displays) else { return }
let allDisplays = prefs.bool(forKey: Utils.PrefKeys.allScreens.rawValue) ? displays : [currentDisplay]
for display in allDisplays {
if (prefs.object(forKey: "\(display.identifier)-state") as? Bool) ?? true {
switch mediaKey {
case .brightnessUp:
let value = display.calcNewValue(for: BRIGHTNESS, withRel: +step)
display.setBrightness(to: value)
case .brightnessDown:
let value = currentDisplay.calcNewValue(for: BRIGHTNESS, withRel: -step)
display.setBrightness(to: value)
case .mute:
display.mute()
case .volumeUp:
let value = display.calcNewValue(for: AUDIO_SPEAKER_VOLUME, withRel: +step)
display.setVolume(to: value)
case .volumeDown:
let value = display.calcNewValue(for: AUDIO_SPEAKER_VOLUME, withRel: -step)
display.setVolume(to: value)
default:
return
}
}
}
}
// MARK: - Prefs notification
@objc func handleListenForChanged() {
let listenFor = prefs.integer(forKey: Utils.PrefKeys.listenFor.rawValue)
keysListenedFor = [.brightnessUp, .brightnessDown, .mute, .volumeUp, .volumeDown]
if listenFor == Utils.ListenForKeys.brightnessOnlyKeys.rawValue {
keysListenedFor.removeSubrange(2...4)
} else if listenFor == Utils.ListenForKeys.volumeOnlyKeys.rawValue {
keysListenedFor.removeSubrange(0...1)
}
mediaKeyTap?.stop()
mediaKeyTap = MediaKeyTap.init(delegate: self, for: keysListenedFor, observeBuiltIn: false)
mediaKeyTap?.start()
}
@objc func handleShowContrastChanged() {
self.updateDisplays()
}
}