Using Applescript for muting/unmuting functionality

This commit is contained in:
Beingpax 2025-05-01 21:41:21 +05:45
parent d234bda390
commit a3418ff2c0

View File

@ -1,19 +1,13 @@
import AppKit
import Combine
import Foundation
import os
import SwiftUI
import CoreAudio
import AudioToolbox
/// Controls system audio management during recording
class MediaController: ObservableObject {
static let shared = MediaController()
private var previousVolume: Float = 1.0
private var didMuteAudio = false
private let logger = Logger(subsystem: "com.prakashjoshipax.voiceink", category: "MediaController")
@Published var isSystemMuteEnabled: Bool = UserDefaults.standard.bool(forKey: "isSystemMuteEnabled") {
didSet {
UserDefaults.standard.set(isSystemMuteEnabled, forKey: "isSystemMuteEnabled")
@ -29,126 +23,37 @@ class MediaController: ObservableObject {
/// Mutes system audio during recording
func muteSystemAudio() async -> Bool {
guard isSystemMuteEnabled else {
logger.info("System mute feature is disabled")
return false
}
guard isSystemMuteEnabled else { return false }
// Get current volume before muting
previousVolume = getSystemVolume()
logger.info("Muting system audio. Previous volume: \(self.previousVolume)")
// Set system volume to 0 (mute)
setSystemVolume(0.0)
didMuteAudio = true
return true
let success = executeAppleScript(command: "set volume with output muted")
didMuteAudio = success
return success
}
/// Restores system audio after recording
func unmuteSystemAudio() async {
guard isSystemMuteEnabled, didMuteAudio else {
return
}
guard isSystemMuteEnabled, didMuteAudio else { return }
logger.info("Unmuting system audio to previous volume: \(self.previousVolume)")
setSystemVolume(previousVolume)
_ = executeAppleScript(command: "set volume without output muted")
didMuteAudio = false
}
/// Gets the current system output volume (0.0 to 1.0)
private func getSystemVolume() -> Float {
var defaultOutputDeviceID = AudioDeviceID(0)
var defaultOutputDeviceIDSize = UInt32(MemoryLayout.size(ofValue: defaultOutputDeviceID))
/// Executes an AppleScript command
private func executeAppleScript(command: String) -> Bool {
let task = Process()
task.launchPath = "/usr/bin/osascript"
task.arguments = ["-e", command]
// Get the default output device
var getDefaultOutputDeviceProperty = AudioObjectPropertyAddress(
mSelector: kAudioHardwarePropertyDefaultOutputDevice,
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMain)
let pipe = Pipe()
task.standardOutput = pipe
task.standardError = pipe
let status = AudioObjectGetPropertyData(
AudioObjectID(kAudioObjectSystemObject),
&getDefaultOutputDeviceProperty,
0,
nil,
&defaultOutputDeviceIDSize,
&defaultOutputDeviceID)
if status != kAudioHardwareNoError {
logger.error("Failed to get default output device: \(status)")
return 1.0 // Default to full volume on error
}
// Get the volume
var volume: Float = 0.0
var volumeSize = UInt32(MemoryLayout.size(ofValue: volume))
var volumeProperty = AudioObjectPropertyAddress(
mSelector: kAudioDevicePropertyVolumeScalar,
mScope: kAudioDevicePropertyScopeOutput,
mElement: kAudioObjectPropertyElementMain)
let volumeStatus = AudioObjectGetPropertyData(
defaultOutputDeviceID,
&volumeProperty,
0,
nil,
&volumeSize,
&volume)
if volumeStatus != kAudioHardwareNoError {
logger.error("Failed to get system volume: \(volumeStatus)")
return 1.0 // Default to full volume on error
}
return volume
}
/// Sets the system output volume (0.0 to 1.0)
private func setSystemVolume(_ volume: Float) {
var defaultOutputDeviceID = AudioDeviceID(0)
var defaultOutputDeviceIDSize = UInt32(MemoryLayout.size(ofValue: defaultOutputDeviceID))
// Get the default output device
var getDefaultOutputDeviceProperty = AudioObjectPropertyAddress(
mSelector: kAudioHardwarePropertyDefaultOutputDevice,
mScope: kAudioObjectPropertyScopeGlobal,
mElement: kAudioObjectPropertyElementMain)
let status = AudioObjectGetPropertyData(
AudioObjectID(kAudioObjectSystemObject),
&getDefaultOutputDeviceProperty,
0,
nil,
&defaultOutputDeviceIDSize,
&defaultOutputDeviceID)
if status != kAudioHardwareNoError {
logger.error("Failed to get default output device: \(status)")
return
}
// Clamp volume to valid range
var safeVolume = max(0.0, min(1.0, volume))
// Set the volume
var volumeProperty = AudioObjectPropertyAddress(
mSelector: kAudioDevicePropertyVolumeScalar,
mScope: kAudioDevicePropertyScopeOutput,
mElement: kAudioObjectPropertyElementMain)
let volumeStatus = AudioObjectSetPropertyData(
defaultOutputDeviceID,
&volumeProperty,
0,
nil,
UInt32(MemoryLayout.size(ofValue: safeVolume)),
&safeVolume)
if volumeStatus != kAudioHardwareNoError {
logger.error("Failed to set system volume: \(volumeStatus)")
} else {
logger.info("Set system volume to \(safeVolume)")
do {
try task.run()
task.waitUntilExit()
return task.terminationStatus == 0
} catch {
return false
}
}
}
@ -162,4 +67,4 @@ extension UserDefaults {
get { bool(forKey: "isSystemMuteEnabled") }
set { set(newValue, forKey: "isSystemMuteEnabled") }
}
}
}