diff --git a/VoiceInk/MediaController.swift b/VoiceInk/MediaController.swift index a27fb29..de67e6e 100644 --- a/VoiceInk/MediaController.swift +++ b/VoiceInk/MediaController.swift @@ -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") } } -} \ No newline at end of file +}