mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-01-11 09:28:38 +00:00
commit
106f297f57
@ -13,6 +13,8 @@
|
|||||||
36C2ECDD207C723B003CDA33 /* ParseConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C2ECDC207C723B003CDA33 /* ParseConfigTests.swift */; };
|
36C2ECDD207C723B003CDA33 /* ParseConfigTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C2ECDC207C723B003CDA33 /* ParseConfigTests.swift */; };
|
||||||
36C2ECDE207C82DE003CDA33 /* ItemsParsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */; };
|
36C2ECDE207C82DE003CDA33 /* ItemsParsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */; };
|
||||||
36C2ECE0207CB1B0003CDA33 /* defaultPreset.json in Resources */ = {isa = PBXBuildFile; fileRef = 36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */; };
|
36C2ECE0207CB1B0003CDA33 /* defaultPreset.json in Resources */ = {isa = PBXBuildFile; fileRef = 36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */; };
|
||||||
|
6027D1B92080E52A004FFDC7 /* BrightnessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */; };
|
||||||
|
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */; };
|
||||||
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; };
|
B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; };
|
||||||
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */; };
|
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */; };
|
||||||
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B059D62C205F11E8006E6B86 /* DFRFoundation.framework */; };
|
B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B059D62C205F11E8006E6B86 /* DFRFoundation.framework */; };
|
||||||
@ -53,6 +55,8 @@
|
|||||||
36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemsParsing.swift; sourceTree = "<group>"; };
|
36C2ECDA207C3FE7003CDA33 /* ItemsParsing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemsParsing.swift; sourceTree = "<group>"; };
|
||||||
36C2ECDC207C723B003CDA33 /* ParseConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseConfigTests.swift; sourceTree = "<group>"; };
|
36C2ECDC207C723B003CDA33 /* ParseConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParseConfigTests.swift; sourceTree = "<group>"; };
|
||||||
36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = defaultPreset.json; sourceTree = "<group>"; };
|
36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = defaultPreset.json; sourceTree = "<group>"; };
|
||||||
|
6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrightnessViewController.swift; sourceTree = "<group>"; };
|
||||||
|
6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VolumeViewController.swift; sourceTree = "<group>"; };
|
||||||
B059D621205E03F5006E6B86 /* TouchBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarController.swift; sourceTree = "<group>"; };
|
B059D621205E03F5006E6B86 /* TouchBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarController.swift; sourceTree = "<group>"; };
|
||||||
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomButtonTouchBarItem.swift; sourceTree = "<group>"; };
|
B059D623205E04F3006E6B86 /* CustomButtonTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomButtonTouchBarItem.swift; sourceTree = "<group>"; };
|
||||||
B059D629205E13E5006E6B86 /* TouchBarPrivateApi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarPrivateApi.h; sourceTree = "<group>"; };
|
B059D629205E13E5006E6B86 /* TouchBarPrivateApi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarPrivateApi.h; sourceTree = "<group>"; };
|
||||||
@ -151,6 +155,8 @@
|
|||||||
B082B25C205C7D8000BC04DC /* MTMR.entitlements */,
|
B082B25C205C7D8000BC04DC /* MTMR.entitlements */,
|
||||||
B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */,
|
B09EB1E3207C082000D5C1E0 /* HapticFeedback.swift */,
|
||||||
36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */,
|
36C2ECDF207CB1B0003CDA33 /* defaultPreset.json */,
|
||||||
|
6027D1B72080E52A004FFDC7 /* BrightnessViewController.swift */,
|
||||||
|
6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */,
|
||||||
);
|
);
|
||||||
path = MTMR;
|
path = MTMR;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -313,10 +319,12 @@
|
|||||||
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
B0F8771A207AC1EA00D6E430 /* TouchBarSupport.m in Sources */,
|
||||||
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */,
|
||||||
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
|
B059D624205E04F3006E6B86 /* CustomButtonTouchBarItem.swift in Sources */,
|
||||||
|
6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */,
|
||||||
B09EB1E4207C082000D5C1E0 /* HapticFeedback.swift in Sources */,
|
B09EB1E4207C082000D5C1E0 /* HapticFeedback.swift in Sources */,
|
||||||
36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */,
|
36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */,
|
||||||
B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */,
|
B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */,
|
||||||
36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */,
|
36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */,
|
||||||
|
6027D1B92080E52A004FFDC7 /* BrightnessViewController.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
45
MTMR/BrightnessViewController.swift
Normal file
45
MTMR/BrightnessViewController.swift
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import Cocoa
|
||||||
|
import AppKit
|
||||||
|
import AVFoundation
|
||||||
|
import CoreAudio
|
||||||
|
|
||||||
|
class BrightnessViewController: NSCustomTouchBarItem {
|
||||||
|
private(set) var sliderItem: NSSlider!
|
||||||
|
|
||||||
|
init(identifier: NSTouchBarItem.Identifier, image: NSImage? = nil) {
|
||||||
|
super.init(identifier: identifier)
|
||||||
|
let brightness:Double = Double(getBrightness())
|
||||||
|
sliderItem = NSSlider(value: brightness*100.0, minValue: 0.0, maxValue: 100.0, target: self, action:#selector(BrightnessViewController.sliderValueChanged(_:)))
|
||||||
|
|
||||||
|
if (image != nil) {
|
||||||
|
sliderItem.cell = CustomSliderCell(knob: image!)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.view = sliderItem
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func sliderValueChanged(_ sender: Any) {
|
||||||
|
if let sliderItem = sender as? NSSlider {
|
||||||
|
setBrightness(level: Float32(sliderItem.intValue)/100.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getBrightness() -> Float32 {
|
||||||
|
var level: Float32 = 0.5
|
||||||
|
let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect"))
|
||||||
|
|
||||||
|
IODisplayGetFloatParameter(service, 0, kIODisplayBrightnessKey as CFString, &level)
|
||||||
|
return level
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setBrightness(level: Float) {
|
||||||
|
let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect"))
|
||||||
|
|
||||||
|
IODisplaySetFloatParameter(service, 0, kIODisplayBrightnessKey as CFString, level)
|
||||||
|
IOObjectRelease(service)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
import AppKit
|
||||||
|
|
||||||
extension Data {
|
extension Data {
|
||||||
|
|
||||||
@ -94,6 +95,8 @@ enum ItemType: Decodable {
|
|||||||
case appleScriptTitledButton(source: Source, refreshInterval: Double)
|
case appleScriptTitledButton(source: Source, refreshInterval: Double)
|
||||||
case timeButton(formatTemplate: String)
|
case timeButton(formatTemplate: String)
|
||||||
case flexSpace()
|
case flexSpace()
|
||||||
|
case volume()
|
||||||
|
case brightness()
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case type
|
case type
|
||||||
@ -110,6 +113,8 @@ enum ItemType: Decodable {
|
|||||||
case appleScriptTitledButton
|
case appleScriptTitledButton
|
||||||
case timeButton
|
case timeButton
|
||||||
case flexSpace
|
case flexSpace
|
||||||
|
case volume
|
||||||
|
case brightness
|
||||||
}
|
}
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
init(from decoder: Decoder) throws {
|
||||||
@ -137,6 +142,10 @@ enum ItemType: Decodable {
|
|||||||
self = .timeButton(formatTemplate: template)
|
self = .timeButton(formatTemplate: template)
|
||||||
case .flexSpace:
|
case .flexSpace:
|
||||||
self = .flexSpace()
|
self = .flexSpace()
|
||||||
|
case .volume:
|
||||||
|
self = .volume()
|
||||||
|
case .brightness:
|
||||||
|
self = .brightness()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,10 @@ extension ItemType {
|
|||||||
return "com.toxblh.mtmr.timeButton."
|
return "com.toxblh.mtmr.timeButton."
|
||||||
case .flexSpace():
|
case .flexSpace():
|
||||||
return "NSTouchBarItem.Identifier.flexibleSpace"
|
return "NSTouchBarItem.Identifier.flexibleSpace"
|
||||||
|
case .volume():
|
||||||
|
return "com.toxblh.mtmr.volume"
|
||||||
|
case .brightness():
|
||||||
|
return "com.toxblh.mtmr.brightness"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +118,10 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
|||||||
barItem = TimeTouchBarItem(identifier: identifier, formatTemplate: template)
|
barItem = TimeTouchBarItem(identifier: identifier, formatTemplate: template)
|
||||||
case .flexSpace:
|
case .flexSpace:
|
||||||
barItem = nil
|
barItem = nil
|
||||||
|
case .volume:
|
||||||
|
barItem = VolumeViewController(identifier: identifier)
|
||||||
|
case .brightness:
|
||||||
|
barItem = BrightnessViewController(identifier: identifier)
|
||||||
}
|
}
|
||||||
for parameter in item.additionalParameters {
|
for parameter in item.additionalParameters {
|
||||||
if case .width(let value) = parameter, let widthBarItem = barItem as? CanSetWidth {
|
if case .width(let value) = parameter, let widthBarItem = barItem as? CanSetWidth {
|
||||||
|
|||||||
122
MTMR/VolumeViewController.swift
Normal file
122
MTMR/VolumeViewController.swift
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import Cocoa
|
||||||
|
import AppKit
|
||||||
|
import AVFoundation
|
||||||
|
import CoreAudio
|
||||||
|
|
||||||
|
class VolumeViewController: NSCustomTouchBarItem {
|
||||||
|
private(set) var sliderItem: NSSlider!
|
||||||
|
|
||||||
|
init(identifier: NSTouchBarItem.Identifier, image: NSImage? = nil) {
|
||||||
|
super.init(identifier: identifier)
|
||||||
|
let volume:Double = Double(getInputGain())
|
||||||
|
sliderItem = NSSlider(value: volume*100, minValue: 0.0, maxValue: 100.0, target: self, action:#selector(VolumeViewController.sliderValueChanged(_:)))
|
||||||
|
|
||||||
|
if (image != nil) {
|
||||||
|
sliderItem.cell = CustomSliderCell(knob: image!)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.view = sliderItem
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func sliderValueChanged(_ sender: Any) {
|
||||||
|
if let sliderItem = sender as? NSSlider {
|
||||||
|
setInputGain(Float32(sliderItem.intValue)/100.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var defaultDeviceID: AudioObjectID {
|
||||||
|
var deviceID: AudioObjectID = AudioObjectID(0)
|
||||||
|
var size: UInt32 = UInt32(MemoryLayout<AudioObjectID>.size)
|
||||||
|
var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress()
|
||||||
|
address.mSelector = AudioObjectPropertySelector(kAudioHardwarePropertyDefaultOutputDevice)
|
||||||
|
address.mScope = AudioObjectPropertyScope(kAudioObjectPropertyScopeGlobal)
|
||||||
|
address.mElement = AudioObjectPropertyElement(kAudioObjectPropertyElementMaster)
|
||||||
|
AudioObjectGetPropertyData(AudioObjectID(kAudioObjectSystemObject), &address, 0, nil, &size, &deviceID)
|
||||||
|
return deviceID
|
||||||
|
}
|
||||||
|
|
||||||
|
private func getInputGain() -> Float32 {
|
||||||
|
var volume: Float32 = 0.5
|
||||||
|
var size: UInt32 = UInt32(MemoryLayout.size(ofValue: volume))
|
||||||
|
var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress()
|
||||||
|
address.mSelector = AudioObjectPropertySelector(kAudioHardwareServiceDeviceProperty_VirtualMasterVolume)
|
||||||
|
address.mScope = AudioObjectPropertyScope(kAudioDevicePropertyScopeOutput)
|
||||||
|
address.mElement = AudioObjectPropertyElement(kAudioObjectPropertyElementMaster)
|
||||||
|
AudioObjectGetPropertyData(defaultDeviceID, &address, 0, nil, &size, &volume)
|
||||||
|
return volume
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setInputGain(_ volume: Float32) -> OSStatus {
|
||||||
|
var inputVolume: Float32 = volume
|
||||||
|
let size: UInt32 = UInt32(MemoryLayout.size(ofValue: inputVolume))
|
||||||
|
var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress()
|
||||||
|
address.mSelector = AudioObjectPropertySelector(kAudioHardwareServiceDeviceProperty_VirtualMasterVolume)
|
||||||
|
address.mScope = AudioObjectPropertyScope(kAudioDevicePropertyScopeOutput)
|
||||||
|
address.mElement = AudioObjectPropertyElement(kAudioObjectPropertyElementMaster)
|
||||||
|
return AudioObjectSetPropertyData(defaultDeviceID, &address, 0, nil, size, &inputVolume)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CustomSliderCell: NSSliderCell {
|
||||||
|
var knobImage:NSImage!
|
||||||
|
private var _currentKnobRect:NSRect!
|
||||||
|
private var _barRect:NSRect!
|
||||||
|
|
||||||
|
required init(coder aDecoder: NSCoder) {
|
||||||
|
super.init(coder: aDecoder)
|
||||||
|
}
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(knob:NSImage) {
|
||||||
|
knobImage = knob;
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func drawKnob(_ knobRect: NSRect) {
|
||||||
|
|
||||||
|
if (knobImage == nil) {
|
||||||
|
super.drawKnob(knobRect)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentKnobRect = knobRect;
|
||||||
|
drawBar(inside: _barRect, flipped: true)
|
||||||
|
self.controlView?.lockFocus()
|
||||||
|
|
||||||
|
knobImage.size.width = knobRect.size.width
|
||||||
|
knobImage.size.height = knobRect.size.height
|
||||||
|
|
||||||
|
let newOriginX:CGFloat = knobRect.origin.x *
|
||||||
|
(_barRect.size.width - (knobImage.size.width - knobRect.size.width)) / _barRect.size.width;
|
||||||
|
|
||||||
|
knobImage.draw(at: NSPoint(x: newOriginX, y: knobRect.origin.y), from: NSRect(x: 0, y: 0, width: knobImage.size.width, height: knobImage.size.height), operation: NSCompositingOperation.sourceOver, fraction: 1)
|
||||||
|
|
||||||
|
self.controlView?.unlockFocus()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override func drawBar(inside aRect: NSRect, flipped: Bool) {
|
||||||
|
_barRect = aRect
|
||||||
|
|
||||||
|
var rect = aRect
|
||||||
|
rect.size.height = CGFloat(3)
|
||||||
|
let barRadius = CGFloat(2.5)
|
||||||
|
let value = CGFloat((self.doubleValue - self.minValue) / (self.maxValue - self.minValue))
|
||||||
|
let finalWidth = CGFloat(value * (self.controlView!.frame.size.width - 8))
|
||||||
|
var leftRect = rect
|
||||||
|
leftRect.size.width = finalWidth
|
||||||
|
let bg = NSBezierPath(roundedRect: rect, xRadius: barRadius, yRadius: barRadius)
|
||||||
|
NSColor.lightGray.setFill()
|
||||||
|
bg.fill()
|
||||||
|
let active = NSBezierPath(roundedRect: leftRect, xRadius: barRadius, yRadius: barRadius)
|
||||||
|
NSColor.darkGray.setFill()
|
||||||
|
active.fill()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,8 @@
|
|||||||
[
|
[
|
||||||
{ "type": "escape" },
|
{ "type": "escape" },
|
||||||
{ "type": "exitTouchbar" },
|
{ "type": "exitTouchbar" },
|
||||||
|
{ "type": "volume", "width": 80 },
|
||||||
|
{ "type": "brightness", "width": 80 },
|
||||||
{ "type": "brightnessDown" },
|
{ "type": "brightnessDown" },
|
||||||
{
|
{
|
||||||
"type": "staticButton",
|
"type": "staticButton",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user