1
0
mirror of https://github.com/Toxblh/MTMR.git synced 2026-01-11 09:28:38 +00:00
MTMR/MTMR/Widgets/VolumeViewController.swift
Fedor Zaitsev 101a81bf3b Refactored parsing
Rewrote presets parsing. Instead of parsing presets in a separate file using bunch of huge enums it is now parsed inside each object.

To implement a new class:
1. Derive your class from CustomTouchBarItem (for static) or CustomButtonTouchBarItem (for buttons)
2. Override class var typeIdentifier with your object identificator
3. Override init(from decoder: Decoder) and read all custom json params you need
4. Don't forget to call super.init(identifier: CustomTouchBarItem.createIdentifier(type)) in the init() function
5. Add your new class to BarItemDefinition.types in ItemParsing.swift

Good example is PomodoroBarItem

If you want to inherid from some other NS class (NSSlider or NSPopoverTouchBarItem or other) then look into GroupBarItem and BrightnessViewController
2020-04-30 22:16:24 -07:00

125 lines
4.8 KiB
Swift

import AppKit
import AVFoundation
import Cocoa
import CoreAudio
class VolumeViewController: CustomTouchBarItem {
private(set) var sliderItem: CustomSlider!
override class var typeIdentifier: String {
return "volume"
}
private enum CodingKeys: String, CodingKey {
case image
}
init(identifier: NSTouchBarItem.Identifier, image: NSImage? = nil) {
super.init(identifier: identifier)
self.setup(image: image)
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let image = try container.decodeIfPresent(Source.self, forKey: .image)?.image
try super.init(from: decoder)
self.setup(image: image)
}
func setup(image: NSImage?) {
var forPropertyAddress = AudioObjectPropertyAddress(
mSelector: kAudioHardwareServiceDeviceProperty_VirtualMasterVolume,
mScope: kAudioDevicePropertyScopeOutput,
mElement: kAudioObjectPropertyElementMaster
)
AudioObjectAddPropertyListenerBlock(defaultDeviceID, &forPropertyAddress, nil, audioObjectPropertyListenerBlock)
if image == nil {
sliderItem = CustomSlider()
} else {
sliderItem = CustomSlider(knob: image!)
}
sliderItem.target = self
sliderItem.action = #selector(VolumeViewController.sliderValueChanged(_:))
sliderItem.minValue = 0.0
sliderItem.maxValue = 100.0
sliderItem.floatValue = getInputGain() * 100
view = sliderItem
}
func audioObjectPropertyListenerBlock(numberAddresses _: UInt32, addresses _: UnsafePointer<AudioObjectPropertyAddress>) {
DispatchQueue.main.async {
self.sliderItem.floatValue = self.getInputGain() * 100
}
}
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
sliderItem.unbind(NSBindingName.value)
}
@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
if inputVolume == 0.0 {
_ = setMute(mute: 1)
} else {
_ = setMute(mute: 0)
}
let size: UInt32 = UInt32(MemoryLayout.size(ofValue: inputVolume))
var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress()
address.mScope = AudioObjectPropertyScope(kAudioDevicePropertyScopeOutput)
address.mElement = AudioObjectPropertyElement(kAudioObjectPropertyElementMaster)
address.mSelector = AudioObjectPropertySelector(kAudioHardwareServiceDeviceProperty_VirtualMasterVolume)
return AudioObjectSetPropertyData(defaultDeviceID, &address, 0, nil, size, &inputVolume)
}
private func setMute(mute: Int) -> OSStatus {
var muteVal: Int = mute
var address: AudioObjectPropertyAddress = AudioObjectPropertyAddress()
address.mSelector = AudioObjectPropertySelector(kAudioDevicePropertyMute)
let size: UInt32 = UInt32(MemoryLayout.size(ofValue: muteVal))
address.mScope = AudioObjectPropertyScope(kAudioDevicePropertyScopeOutput)
address.mElement = AudioObjectPropertyElement(kAudioObjectPropertyElementMaster)
return AudioObjectSetPropertyData(defaultDeviceID, &address, 0, nil, size, &muteVal)
}
}