mirror of
https://github.com/MonitorControl/MonitorControl.git
synced 2026-05-15 14:15:55 -06:00
Only show attached monitors and use ddcctl directly
This commit is contained in:
parent
8de9597139
commit
d4efada906
5 changed files with 191 additions and 72 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "ddcctl"]
|
||||
path = ddcctl
|
||||
url = https://github.com/kfix/ddcctl
|
||||
|
|
@ -7,12 +7,23 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
55359E391E2737EC002671BC /* DDC.c in Sources */ = {isa = PBXBuildFile; fileRef = 55359E331E2737EC002671BC /* DDC.c */; };
|
||||
55359E3B1E2737EC002671BC /* ddcctl.sh in Resources */ = {isa = PBXBuildFile; fileRef = 55359E361E2737EC002671BC /* ddcctl.sh */; };
|
||||
55359E3C1E2737EC002671BC /* Makefile in Sources */ = {isa = PBXBuildFile; fileRef = 55359E371E2737EC002671BC /* Makefile */; };
|
||||
55359E3D1E2737EC002671BC /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 55359E381E2737EC002671BC /* README.md */; };
|
||||
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 */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
55359E331E2737EC002671BC /* DDC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = DDC.c; sourceTree = "<group>"; };
|
||||
55359E341E2737EC002671BC /* DDC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDC.h; sourceTree = "<group>"; };
|
||||
55359E351E2737EC002671BC /* ddcctl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ddcctl.m; sourceTree = "<group>"; };
|
||||
55359E361E2737EC002671BC /* ddcctl.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ddcctl.sh; sourceTree = "<group>"; };
|
||||
55359E371E2737EC002671BC /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
|
||||
55359E381E2737EC002671BC /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||
55359E3E1E27380B002671BC /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
56754EAB1D9A4016007BCDC5 /* MonitorControl.OSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MonitorControl.OSX.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
56754EB01D9A4016007BCDC5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
|
|
@ -31,10 +42,24 @@
|
|||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
55359E321E2737EC002671BC /* ddcctl */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
55359E331E2737EC002671BC /* DDC.c */,
|
||||
55359E341E2737EC002671BC /* DDC.h */,
|
||||
55359E351E2737EC002671BC /* ddcctl.m */,
|
||||
55359E361E2737EC002671BC /* ddcctl.sh */,
|
||||
55359E371E2737EC002671BC /* Makefile */,
|
||||
55359E381E2737EC002671BC /* README.md */,
|
||||
);
|
||||
path = ddcctl;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
56754EA21D9A4016007BCDC5 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
56754EAD1D9A4016007BCDC5 /* MonitorControl.OSX */,
|
||||
55359E321E2737EC002671BC /* ddcctl */,
|
||||
56754EAC1D9A4016007BCDC5 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -54,6 +79,7 @@
|
|||
56754EB01D9A4016007BCDC5 /* Assets.xcassets */,
|
||||
56754EB21D9A4016007BCDC5 /* MainMenu.xib */,
|
||||
56754EB51D9A4016007BCDC5 /* Info.plist */,
|
||||
55359E3E1E27380B002671BC /* Bridging-Header.h */,
|
||||
);
|
||||
path = MonitorControl.OSX;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -118,6 +144,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
56754EB11D9A4016007BCDC5 /* Assets.xcassets in Resources */,
|
||||
55359E3B1E2737EC002671BC /* ddcctl.sh in Resources */,
|
||||
56754EB41D9A4016007BCDC5 /* MainMenu.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -130,6 +157,9 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
56754EAF1D9A4016007BCDC5 /* AppDelegate.swift in Sources */,
|
||||
55359E3D1E2737EC002671BC /* README.md in Sources */,
|
||||
55359E3C1E2737EC002671BC /* Makefile in Sources */,
|
||||
55359E391E2737EC002671BC /* DDC.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -246,6 +276,7 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "bluejamesbond.MonitorControl-OSX";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "MonitorControl.OSX/Bridging-Header.h";
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Debug;
|
||||
|
|
@ -259,6 +290,7 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "bluejamesbond.MonitorControl-OSX";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "MonitorControl.OSX/Bridging-Header.h";
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Release;
|
||||
|
|
@ -282,6 +314,7 @@
|
|||
56754EBA1D9A4016007BCDC5 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@
|
|||
import Cocoa
|
||||
import Foundation
|
||||
|
||||
struct Display {
|
||||
var id: CGDirectDisplayID
|
||||
var name: String
|
||||
var serial: String
|
||||
}
|
||||
|
||||
@NSApplicationMain
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
|
|
@ -20,6 +26,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
let statusItem = NSStatusBar.system().statusItem(withLength: NSVariableStatusItemLength)
|
||||
|
||||
let keycode = UInt16(0x07)
|
||||
|
||||
var displays : [Display] = []
|
||||
|
||||
@IBAction func quitClicked(_ sender: AnyObject) {
|
||||
NSApplication.shared().terminate(self);
|
||||
|
|
@ -28,117 +36,140 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
func setBrightness( slider: NSSlider ){
|
||||
let command = "-b";
|
||||
let value = slider.integerValue;
|
||||
let monitor = slider.tag;
|
||||
let i = slider.tag;
|
||||
let d = displays[i]
|
||||
|
||||
ddcctl(monitor: String(monitor), command: command, value: String(value));
|
||||
ddcctl(monitor: d.id, command: command, value: value);
|
||||
|
||||
prefs.setValue(value, forKey: "\(command)-\(monitor)");
|
||||
prefs.setValue(value, forKey: "\(command)-\(d.serial)");
|
||||
prefs.synchronize();
|
||||
}
|
||||
|
||||
func setVolume(slider: NSSlider ){
|
||||
let command = "-v";
|
||||
let value = slider.integerValue;
|
||||
let monitor = slider.tag;
|
||||
|
||||
ddcctl(monitor: String(monitor), command: command, value: String(value));
|
||||
|
||||
prefs.setValue(value, forKey: "\(command)-\(monitor)");
|
||||
let i = slider.tag;
|
||||
let d = displays[i]
|
||||
|
||||
ddcctl(monitor: d.id, command: command, value: value);
|
||||
|
||||
prefs.setValue(value, forKey: "\(command)-\(d.serial)");
|
||||
prefs.synchronize();
|
||||
}
|
||||
|
||||
|
||||
func setContrast(slider: NSSlider ){
|
||||
let command = "-c";
|
||||
let value = slider.integerValue;
|
||||
let monitor = slider.tag;
|
||||
|
||||
ddcctl(monitor: String(monitor), command: command, value: String(value));
|
||||
|
||||
prefs.setValue(value, forKey: "\(command)-\(monitor)");
|
||||
let i = slider.tag;
|
||||
let d = displays[i]
|
||||
|
||||
ddcctl(monitor: d.id, command: command, value: value);
|
||||
|
||||
prefs.setValue(value, forKey: "\(command)-\(d.serial)");
|
||||
prefs.synchronize();
|
||||
}
|
||||
|
||||
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
statusItem.title = "♨"
|
||||
statusItem.menu = statusMenu;
|
||||
|
||||
for i in (1...4).reversed() {
|
||||
statusItem.menu = statusMenu
|
||||
|
||||
var firstDisplay : Display? = nil
|
||||
|
||||
for s in NSScreen.screens()! {
|
||||
let id = s.deviceDescription["NSScreenNumber"] as! CGDirectDisplayID
|
||||
if CGDisplayIsBuiltin(id) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var edid = EDID()
|
||||
if !EDIDTest(id, &edid) {
|
||||
continue
|
||||
}
|
||||
|
||||
let name = getDisplayName(edid)
|
||||
let serial = getDisplaySerial(edid)
|
||||
|
||||
let d = Display(id: id, name: name, serial: serial)
|
||||
displays.append(d)
|
||||
|
||||
let i = displays.count - 1
|
||||
|
||||
let monitorMenuItem = NSMenuItem();
|
||||
let monitorSubMenu = NSMenu();
|
||||
|
||||
|
||||
let brightnessItem = NSMenuItem();
|
||||
let contrastItem = NSMenuItem();
|
||||
let volumeItem = NSMenuItem();
|
||||
let defaultMonitorItem = NSMenuItem();
|
||||
|
||||
let brightnessSlider = NSSlider(frame: NSRect(x: 20, y: 0, width: 200, height: 19));
|
||||
|
||||
|
||||
brightnessSlider.target = self;
|
||||
brightnessSlider.minValue = 0;
|
||||
brightnessSlider.maxValue = 100;
|
||||
brightnessSlider.integerValue = prefs.integer(forKey: "-b-\(i)")
|
||||
brightnessSlider.integerValue = prefs.integer(forKey: "-b-\(serial)")
|
||||
brightnessSlider.action = #selector(AppDelegate.setBrightness);
|
||||
brightnessSlider.tag = i;
|
||||
|
||||
|
||||
let contrastSlider = NSSlider(frame: NSRect(x: 20, y: 0, width: 200, height: 19));
|
||||
|
||||
|
||||
contrastSlider.target = self;
|
||||
contrastSlider.minValue = 0;
|
||||
contrastSlider.maxValue = 100;
|
||||
contrastSlider.integerValue = prefs.integer(forKey: "-c-\(i)")
|
||||
contrastSlider.integerValue = prefs.integer(forKey: "-c-\(serial)")
|
||||
contrastSlider.action = #selector(AppDelegate.setContrast);
|
||||
contrastSlider.tag = i;
|
||||
|
||||
|
||||
let volumeSlider = NSSlider(frame: NSRect(x: 20, y: 3, width: 200, height: 19));
|
||||
|
||||
|
||||
volumeSlider.target = self;
|
||||
volumeSlider.minValue = 0;
|
||||
volumeSlider.maxValue = 100;
|
||||
volumeSlider.integerValue = prefs.integer(forKey: "-v-\(i)")
|
||||
volumeSlider.integerValue = prefs.integer(forKey: "-v-\(serial)")
|
||||
volumeSlider.action = #selector(AppDelegate.setVolume);
|
||||
volumeSlider.tag = i;
|
||||
|
||||
|
||||
let brightnesSliderView = NSView(frame: NSRect(x: 0, y: 5, width: 250, height: 40));
|
||||
let contrastSliderView = NSView(frame: NSRect(x: 0, y: 5, width: 250, height: 40));
|
||||
let volumeSliderView = NSView(frame: NSRect(x: 0, y: 5, width: 250, height: 40));
|
||||
let defaultMonitorView = NSView(frame: NSRect(x: 0, y: 5, width: 250, height: 25));
|
||||
|
||||
|
||||
let brightnessLabel = NSTextField(frame: NSRect(x: 20, y: 16, width: 130, height: 20))
|
||||
brightnessLabel.stringValue = "Brightness";
|
||||
brightnessLabel.isBordered = false;
|
||||
brightnessLabel.isBezeled = false;
|
||||
|
||||
|
||||
let brightnessLabelKeyCode = NSTextField(frame: NSRect(x: 120, y: 16, width: 100, height: 20))
|
||||
brightnessLabelKeyCode.stringValue = "⇧⌘- / ⇧⌘+"
|
||||
brightnessLabelKeyCode.isBordered = false;
|
||||
brightnessLabelKeyCode.isBezeled = false;
|
||||
brightnessLabelKeyCode.isHidden = i != 1;
|
||||
brightnessLabelKeyCode.isHidden = firstDisplay == nil;
|
||||
brightnessLabelKeyCode.alignment = NSTextAlignment.right
|
||||
|
||||
|
||||
let constrastLabel = NSTextField(frame: NSRect(x: 20, y: 16, width: 130, height: 20))
|
||||
constrastLabel.stringValue = "Contrast"
|
||||
constrastLabel.isBordered = false;
|
||||
constrastLabel.isBezeled = false;
|
||||
|
||||
|
||||
let volumeLabel = NSTextField(frame: NSRect(x: 20, y: 19, width: 130, height: 20))
|
||||
volumeLabel.stringValue = "Volume"
|
||||
volumeLabel.isBordered = false;
|
||||
volumeLabel.isBezeled = false;
|
||||
|
||||
|
||||
let volumeLabelKeyCode = NSTextField(frame: NSRect(x: 120, y: 19, width: 100, height: 20))
|
||||
volumeLabelKeyCode.stringValue = "⌥⌘- / ⌥⌘+"
|
||||
volumeLabelKeyCode.isBordered = false;
|
||||
volumeLabelKeyCode.isBezeled = false;
|
||||
volumeLabelKeyCode.isHidden = i != 1;
|
||||
volumeLabelKeyCode.isHidden = firstDisplay == nil;
|
||||
volumeLabelKeyCode.alignment = NSTextAlignment.right
|
||||
|
||||
|
||||
brightnesSliderView.addSubview(brightnessLabel)
|
||||
brightnesSliderView.addSubview(brightnessLabelKeyCode)
|
||||
brightnesSliderView.addSubview(brightnessSlider)
|
||||
|
||||
contrastSliderView.addSubview(constrastLabel)
|
||||
contrastSliderView.addSubview(contrastSlider)
|
||||
|
||||
|
||||
volumeSliderView.addSubview(volumeLabel)
|
||||
volumeSliderView.addSubview(volumeLabelKeyCode)
|
||||
volumeSliderView.addSubview(volumeSlider)
|
||||
|
|
@ -146,17 +177,17 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
brightnessItem.view = brightnesSliderView;
|
||||
contrastItem.view = contrastSliderView;
|
||||
volumeItem.view = volumeSliderView;
|
||||
|
||||
|
||||
let defaultMonitorSelectButtom = NSButton(frame: NSRect(x: 25, y: 0, width: 200, height: 25));
|
||||
defaultMonitorSelectButtom.title = i == 1 ? "Default" : "Set as default";
|
||||
defaultMonitorSelectButtom.title = firstDisplay == nil ? "Default" : "Set as default";
|
||||
defaultMonitorSelectButtom.bezelStyle = NSRoundRectBezelStyle;
|
||||
defaultMonitorSelectButtom.isEnabled = i != 1;
|
||||
defaultMonitorSelectButtom.isEnabled = firstDisplay == nil;
|
||||
defaultMonitorSelectButtom.tag = i;
|
||||
|
||||
|
||||
defaultMonitorView.addSubview(defaultMonitorSelectButtom);
|
||||
|
||||
|
||||
defaultMonitorItem.view = defaultMonitorView;
|
||||
|
||||
|
||||
monitorSubMenu.addItem(brightnessItem);
|
||||
monitorSubMenu.addItem(NSMenuItem.separator());
|
||||
monitorSubMenu.addItem(contrastItem);
|
||||
|
|
@ -165,53 +196,59 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
monitorSubMenu.addItem(NSMenuItem.separator());
|
||||
monitorSubMenu.addItem(defaultMonitorItem);
|
||||
|
||||
monitorMenuItem.title = "Monitor \(i)";
|
||||
monitorMenuItem.title = "\(name)";
|
||||
monitorMenuItem.submenu = monitorSubMenu;
|
||||
|
||||
|
||||
statusMenu.insertItem(monitorMenuItem, at: 0)
|
||||
|
||||
if firstDisplay == nil {
|
||||
firstDisplay = d
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
acquirePrivileges();
|
||||
|
||||
|
||||
if firstDisplay == nil {
|
||||
return
|
||||
}
|
||||
|
||||
let d = firstDisplay!
|
||||
|
||||
NSEvent.addGlobalMonitorForEvents(
|
||||
matching: NSEventMask.keyDown, handler: {(event: NSEvent) in
|
||||
if (event.keyCode == 27 &&
|
||||
(event.modifierFlags.contains(NSEventModifierFlags.control)) &&
|
||||
(event.modifierFlags.contains(NSEventModifierFlags.command))) {
|
||||
let monitor = 1;
|
||||
let value = abs(self.prefs.integer(forKey: "-v-\(monitor)") - 1);
|
||||
|
||||
self.prefs.setValue(value, forKey: "-v-\(monitor)");
|
||||
|
||||
self.ddcctl(monitor: String(monitor), command: "-v", value: String(value));
|
||||
let value = abs(self.prefs.integer(forKey: "-v-\(d.serial)") - 1);
|
||||
|
||||
self.prefs.setValue(value, forKey: "-v-\(d.serial)");
|
||||
|
||||
self.ddcctl(monitor: d.id, command: "-v", value: value);
|
||||
|
||||
} else if (event.keyCode == 24 &&
|
||||
(event.modifierFlags.contains(NSEventModifierFlags.control)) &&
|
||||
(event.modifierFlags.contains(NSEventModifierFlags.command))) {
|
||||
let monitor = 1;
|
||||
let value = abs(self.prefs.integer(forKey: "-v-\(monitor)") + 1);
|
||||
let value = abs(self.prefs.integer(forKey: "-v-\(d.serial)") + 1);
|
||||
|
||||
self.prefs.setValue(value, forKey: "-v-\(monitor)");
|
||||
self.prefs.setValue(value, forKey: "-v-\(d.serial)");
|
||||
|
||||
self.ddcctl(monitor: String(monitor), command: "-v", value: String(value));
|
||||
self.ddcctl(monitor: d.id, command: "-v", value: value);
|
||||
} else if (event.keyCode == 27 &&
|
||||
(event.modifierFlags.contains(NSEventModifierFlags.option)) &&
|
||||
(event.modifierFlags.contains(NSEventModifierFlags.command))) {
|
||||
let monitor = 1;
|
||||
let value = abs(self.prefs.integer(forKey: "-b-\(monitor)") - 1);
|
||||
let value = abs(self.prefs.integer(forKey: "-b-\(d.serial)") - 1);
|
||||
|
||||
self.prefs.setValue(value, forKey: "-b-\(monitor)");
|
||||
self.prefs.setValue(value, forKey: "-b-\(d.serial))");
|
||||
|
||||
self.ddcctl(monitor: String(monitor), command: "-b", value: String(value));
|
||||
self.ddcctl(monitor: d.id, command: "-b", value: value);
|
||||
} else if (event.keyCode == 24 &&
|
||||
(event.modifierFlags.contains(NSEventModifierFlags.option)) &&
|
||||
(event.modifierFlags.contains(NSEventModifierFlags.command))) {
|
||||
let monitor = 1;
|
||||
let value = abs(self.prefs.integer(forKey: "-b-\(monitor)") + 1);
|
||||
let value = abs(self.prefs.integer(forKey: "-b-\(d.serial)") + 1);
|
||||
|
||||
self.prefs.setValue(value, forKey: "-b-\(monitor)");
|
||||
self.prefs.setValue(value, forKey: "-b-\(d.serial)");
|
||||
|
||||
self.ddcctl(monitor: String(monitor), command: "-b", value: String(value));
|
||||
self.ddcctl(monitor: d.id, command: "-b", value: value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -227,16 +264,59 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
return;
|
||||
}
|
||||
|
||||
func ddcctl(monitor: String, command: String, value: String) {
|
||||
let task = Process()
|
||||
|
||||
task.launchPath = "/usr/local/bin/ddcctl"
|
||||
task.arguments = ["-d", monitor, command, value]
|
||||
task.launch()
|
||||
func ddcctl(monitor: CGDirectDisplayID, command: String, value: Int) {
|
||||
var cmd : Int32! = nil
|
||||
switch command {
|
||||
case "-b":
|
||||
cmd = BRIGHTNESS
|
||||
break
|
||||
case "-v":
|
||||
cmd = AUDIO_SPEAKER_VOLUME
|
||||
break
|
||||
case "-c":
|
||||
cmd = CONTRAST
|
||||
break
|
||||
default:
|
||||
precondition(false, "Unknown command: \(command)")
|
||||
}
|
||||
|
||||
var wrcmd = DDCWriteCommand(control_id: UInt8(cmd), new_value: UInt8(value))
|
||||
DDCWrite(monitor, &wrcmd)
|
||||
print(value)
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ aNotification: Notification) {
|
||||
// Insert code here to tear down your application
|
||||
}
|
||||
|
||||
|
||||
func edidString(_ d: descriptor) -> String {
|
||||
var s = ""
|
||||
for (_, b) in Mirror(reflecting: d.text.data).children {
|
||||
let b = b as! Int8
|
||||
let c = Character(UnicodeScalar(UInt8(bitPattern: b)))
|
||||
if c == "\0" || c == "\n" {
|
||||
break
|
||||
}
|
||||
s.append(c)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func getDescriptorString(_ edid: EDID, _ type: UInt8) -> String? {
|
||||
for d in [edid.descriptor1, edid.descriptor2, edid.descriptor3, edid.descriptor4] {
|
||||
if d.text.type == UInt8(type) {
|
||||
return edidString(d)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getDisplayName(_ edid: EDID) -> String {
|
||||
return getDescriptorString(edid, 0xFC) ?? "Display"
|
||||
}
|
||||
|
||||
func getDisplaySerial(_ edid: EDID) -> String {
|
||||
return getDescriptorString(edid, 0xFF) ?? "Unknown"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
MonitorControl.OSX/Bridging-Header.h
Normal file
2
MonitorControl.OSX/Bridging-Header.h
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
#include "../ddcctl/DDC.h"
|
||||
1
ddcctl
Submodule
1
ddcctl
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit dda64ce43cdf0c16b2bedcf744033911a2bb88c5
|
||||
Loading…
Add table
Add a link
Reference in a new issue