mirror of
https://github.com/MonitorControl/MonitorControl.git
synced 2026-05-15 14:15:55 -06:00
♻️ Refactoring + Identifier + Mute
- I've rewritten some so it should easier to read now - Mute should work like on a mac, meaning you can mute and unmute back to the previous volume - Removed the "default" system as I now use the "main" screen for keyboard shortcuts, meaning, in a multiple screen environement you can now control the current screen with your keyboard - I now use the `identifier` instead of `serial` of the display for saving value, should fix (hopefully) #6 Signed-off-by: Guillaume Broder <iamnotheoneyouseek@gmail.com>
This commit is contained in:
parent
e45fb6e705
commit
1112380361
5 changed files with 115 additions and 82 deletions
|
|
@ -25,11 +25,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate {
|
|||
|
||||
var monitorItems: [NSMenuItem] = []
|
||||
var displays: [Display] = []
|
||||
var sliderHandlers: [SliderHandler] = []
|
||||
|
||||
var defaultDisplay: Display! = nil
|
||||
var defaultBrightnessSlider: NSSlider! = nil
|
||||
var defaultVolumeSlider: NSSlider! = nil
|
||||
|
||||
let step = 100/16
|
||||
|
||||
|
|
@ -89,17 +84,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate {
|
|||
// MARK: - Menu
|
||||
|
||||
func clearDisplays() {
|
||||
defaultDisplay = nil
|
||||
defaultBrightnessSlider = nil
|
||||
defaultVolumeSlider = nil
|
||||
|
||||
for monitor in monitorItems {
|
||||
statusMenu.removeItem(monitor)
|
||||
}
|
||||
|
||||
monitorItems = []
|
||||
displays = []
|
||||
sliderHandlers = []
|
||||
}
|
||||
|
||||
func updateDisplays() {
|
||||
|
|
@ -122,8 +112,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate {
|
|||
let name = Utils.getDisplayName(forEdid: edid)
|
||||
let serial = Utils.getDisplaySerial(forEdid: edid)
|
||||
|
||||
let display = Display(identifier: id, name: name, serial: serial, isEnabled: true)
|
||||
displays.append(display)
|
||||
let display = Display.init(id, name: name, serial: serial)
|
||||
|
||||
let monitorSubMenu = NSMenu()
|
||||
let brightnessSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu,
|
||||
|
|
@ -134,21 +123,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate {
|
|||
forDisplay: display,
|
||||
command: AUDIO_SPEAKER_VOLUME,
|
||||
title: NSLocalizedString("Volume", comment: "Shown in menu"))
|
||||
sliderHandlers.append(brightnessSliderHandler)
|
||||
sliderHandlers.append(volumeSliderHandler)
|
||||
|
||||
let isDefaultDisplay = defaultDisplay == nil
|
||||
let defaultMonitorSelectButtom = NSButton(frame: NSRect(x: 25, y: 0, width: 200, height: 25))
|
||||
defaultMonitorSelectButtom.title = isDefaultDisplay ? NSLocalizedString("Default", comment: "Shown in menu") : NSLocalizedString("Set as default", comment: "Shown in menu")
|
||||
defaultMonitorSelectButtom.bezelStyle = NSButton.BezelStyle.rounded
|
||||
defaultMonitorSelectButtom.isEnabled = !isDefaultDisplay
|
||||
|
||||
let defaultMonitorView = NSView(frame: NSRect(x: 0, y: 5, width: 250, height: 25))
|
||||
defaultMonitorView.addSubview(defaultMonitorSelectButtom)
|
||||
|
||||
let defaultMonitorItem = NSMenuItem()
|
||||
defaultMonitorItem.view = defaultMonitorView
|
||||
monitorSubMenu.addItem(defaultMonitorItem)
|
||||
display.brightnessSliderHandler = brightnessSliderHandler
|
||||
display.volumeSliderHandler = volumeSliderHandler
|
||||
displays.append(display)
|
||||
|
||||
let monitorMenuItem = NSMenuItem()
|
||||
monitorMenuItem.title = "\(name)"
|
||||
|
|
@ -156,16 +133,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate {
|
|||
|
||||
monitorItems.append(monitorMenuItem)
|
||||
statusMenu.insertItem(monitorMenuItem, at: displays.count - 1)
|
||||
|
||||
if isDefaultDisplay {
|
||||
defaultDisplay = display
|
||||
defaultBrightnessSlider = brightnessSliderHandler.slider
|
||||
defaultVolumeSlider = volumeSliderHandler.slider
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if defaultDisplay == nil {
|
||||
if displays.count == 0 {
|
||||
// If no DDC capable display was detected
|
||||
let item = NSMenuItem()
|
||||
item.title = NSLocalizedString("No supported display found", comment: "Shown in menu")
|
||||
|
|
@ -178,60 +149,32 @@ class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate {
|
|||
// MARK: - Media Key Tap delegate
|
||||
|
||||
func handle(mediaKey: MediaKey, event: KeyEvent) {
|
||||
|
||||
var command = BRIGHTNESS
|
||||
guard let currentDisplay = Utils.getCurrentDisplay(from: displays) else { return }
|
||||
var rel = 0
|
||||
var slider = self.defaultBrightnessSlider
|
||||
|
||||
switch mediaKey {
|
||||
case .brightnessUp:
|
||||
rel = +self.step
|
||||
let value = currentDisplay.calcNewValue(for: BRIGHTNESS, withRel: rel)
|
||||
currentDisplay.setBrightness(to: value)
|
||||
case .brightnessDown:
|
||||
rel = -self.step
|
||||
let value = currentDisplay.calcNewValue(for: BRIGHTNESS, withRel: rel)
|
||||
currentDisplay.setBrightness(to: value)
|
||||
case .mute:
|
||||
rel = -100
|
||||
command = AUDIO_SPEAKER_VOLUME
|
||||
slider = self.defaultVolumeSlider
|
||||
currentDisplay.mute()
|
||||
case .volumeUp:
|
||||
rel = +self.step
|
||||
command = AUDIO_SPEAKER_VOLUME
|
||||
slider = self.defaultVolumeSlider
|
||||
let value = currentDisplay.calcNewValue(for: AUDIO_SPEAKER_VOLUME, withRel: rel)
|
||||
currentDisplay.setVolume(to: value)
|
||||
case .volumeDown:
|
||||
rel = -self.step
|
||||
command = AUDIO_SPEAKER_VOLUME
|
||||
slider = self.defaultVolumeSlider
|
||||
let value = currentDisplay.calcNewValue(for: AUDIO_SPEAKER_VOLUME, withRel: rel)
|
||||
currentDisplay.setVolume(to: value)
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
let k = "\(command)-\(self.defaultDisplay.serial)"
|
||||
let value = max(0, min(100, prefs.integer(forKey: k) + rel))
|
||||
prefs.setValue(value, forKey: k)
|
||||
prefs.synchronize()
|
||||
|
||||
if let slider = slider {
|
||||
slider.intValue = Int32(value)
|
||||
}
|
||||
|
||||
Utils.ddcctl(monitor: self.defaultDisplay.identifier, command: command, value: value)
|
||||
|
||||
// OSD
|
||||
if let manager = OSDManager.sharedManager() as? OSDManager {
|
||||
var osdImage: Int64 = 1 // Brightness Image
|
||||
if command == AUDIO_SPEAKER_VOLUME {
|
||||
osdImage = 3 // Speaker image
|
||||
if value == 0 {
|
||||
osdImage = 4 // Mute speaker
|
||||
}
|
||||
}
|
||||
manager.showImage(osdImage,
|
||||
onDisplayID: self.defaultDisplay.identifier,
|
||||
priority: 0x1f4,
|
||||
msecUntilFade: 2000,
|
||||
filledChiclets: UInt32(value/self.step),
|
||||
totalChiclets: UInt32(100/self.step),
|
||||
locked: false)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,86 @@
|
|||
import Cocoa
|
||||
|
||||
/// A display
|
||||
struct Display {
|
||||
var identifier: CGDirectDisplayID
|
||||
var name: String
|
||||
var serial: String
|
||||
var isEnabled: Bool = true
|
||||
class Display {
|
||||
let identifier: CGDirectDisplayID
|
||||
let name: String
|
||||
let serial: String
|
||||
var isEnabled: Bool
|
||||
var isMuted: Bool = false
|
||||
var brightnessSliderHandler: SliderHandler?
|
||||
var volumeSliderHandler: SliderHandler?
|
||||
|
||||
init(_ identifier: CGDirectDisplayID, name: String, serial: String, isEnabled: Bool = true) {
|
||||
self.identifier = identifier
|
||||
self.name = name
|
||||
self.serial = serial
|
||||
self.isEnabled = isEnabled
|
||||
}
|
||||
|
||||
func mute() {
|
||||
var value = 0
|
||||
if isMuted {
|
||||
value = UserDefaults.standard.integer(forKey: "\(AUDIO_SPEAKER_VOLUME)-\(identifier)")
|
||||
isMuted = false
|
||||
} else {
|
||||
isMuted = true
|
||||
}
|
||||
|
||||
Utils.ddcctl(monitor: identifier, command: AUDIO_SPEAKER_VOLUME, value: value)
|
||||
if let slider = volumeSliderHandler?.slider {
|
||||
slider.intValue = Int32(value)
|
||||
}
|
||||
showOsd(command: AUDIO_SPEAKER_VOLUME, value: value)
|
||||
}
|
||||
|
||||
func setVolume(to value: Int) {
|
||||
if value > 0 {
|
||||
isMuted = false
|
||||
}
|
||||
|
||||
Utils.ddcctl(monitor: identifier, command: AUDIO_SPEAKER_VOLUME, value: value)
|
||||
if let slider = volumeSliderHandler?.slider {
|
||||
slider.intValue = Int32(value)
|
||||
}
|
||||
showOsd(command: AUDIO_SPEAKER_VOLUME, value: value)
|
||||
saveValue(value, for: AUDIO_SPEAKER_VOLUME)
|
||||
}
|
||||
|
||||
func setBrightness(to value: Int) {
|
||||
Utils.ddcctl(monitor: identifier, command: BRIGHTNESS, value: value)
|
||||
if let slider = brightnessSliderHandler?.slider {
|
||||
slider.intValue = Int32(value)
|
||||
}
|
||||
showOsd(command: BRIGHTNESS, value: value)
|
||||
saveValue(value, for: BRIGHTNESS)
|
||||
}
|
||||
|
||||
func calcNewValue(for command: Int32, withRel rel: Int) -> Int {
|
||||
let currentValue = UserDefaults.standard.integer(forKey: "\(command)-\(identifier)")
|
||||
return max(0, min(100, currentValue + rel))
|
||||
}
|
||||
|
||||
func saveValue(_ value: Int, for command: Int32) {
|
||||
UserDefaults.standard.set(value, forKey: "\(command)-\(identifier)")
|
||||
}
|
||||
|
||||
private func showOsd(command: Int32, value: Int) {
|
||||
if let manager = OSDManager.sharedManager() as? OSDManager {
|
||||
var osdImage: Int64 = 1 // Brightness Image
|
||||
if command == AUDIO_SPEAKER_VOLUME {
|
||||
osdImage = 3 // Speaker image
|
||||
if isMuted {
|
||||
osdImage = 4 // Mute speaker
|
||||
}
|
||||
}
|
||||
let step = 100/16
|
||||
manager.showImage(osdImage,
|
||||
onDisplayID: identifier,
|
||||
priority: 0x1f4,
|
||||
msecUntilFade: 2000,
|
||||
filledChiclets: UInt32(value/step),
|
||||
totalChiclets: UInt32(100/step),
|
||||
locked: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ class SliderHandler {
|
|||
}
|
||||
|
||||
Utils.ddcctl(monitor: display.identifier, command: command, value: value)
|
||||
|
||||
prefs.setValue(value, forKey: "\(command)-\(display.serial)")
|
||||
prefs.synchronize()
|
||||
prefs.setValue(value, forKey: "\(command)-\(display.identifier)")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class DisplayPrefsViewController: NSViewController, MASPreferencesViewController
|
|||
if let id = screen.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as? CGDirectDisplayID {
|
||||
// Is Built In Screen (e.g. MBP/iMac Screen)
|
||||
if CGDisplayIsBuiltin(id) != 0 {
|
||||
let display = Display(identifier: id, name: "Mac built-in Display", serial: "", isEnabled: false)
|
||||
let display = Display(id, name: "Mac built-in Display", serial: "", isEnabled: false)
|
||||
displays.append(display)
|
||||
continue
|
||||
}
|
||||
|
|
@ -71,7 +71,7 @@ class DisplayPrefsViewController: NSViewController, MASPreferencesViewController
|
|||
isEnabled = enabled
|
||||
}
|
||||
|
||||
let display = Display(identifier: id, name: name, serial: serial, isEnabled: isEnabled)
|
||||
let display = Display(id, name: name, serial: serial, isEnabled: isEnabled)
|
||||
displays.append(display)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,6 +147,21 @@ class Utils: NSObject {
|
|||
return getDescriptorString(edid, 0xFF) ?? NSLocalizedString("Unknown", comment: "")
|
||||
}
|
||||
|
||||
/// Get the main display from a list of display
|
||||
///
|
||||
/// - Parameter displays: List of Display
|
||||
/// - Returns: the main display or nil if not found
|
||||
static func getCurrentDisplay(from displays: [Display]) -> Display? {
|
||||
return displays.first { display -> Bool in
|
||||
if let main = NSScreen.main {
|
||||
if let id = main.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as? CGDirectDisplayID {
|
||||
return display.identifier == id
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/// UserDefault Keys for the app prefs
|
||||
enum PrefKeys: String {
|
||||
/// Was the app launched once
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue