Simplify audio input modes: keep Custom and Prioritized, remove System Default option
This commit is contained in:
parent
8f48c91642
commit
a3226bb0fb
@ -10,7 +10,6 @@ struct PrioritizedDevice: Codable, Identifiable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum AudioInputMode: String, CaseIterable {
|
enum AudioInputMode: String, CaseIterable {
|
||||||
case systemDefault = "System Default"
|
|
||||||
case custom = "Custom Device"
|
case custom = "Custom Device"
|
||||||
case prioritized = "Prioritized"
|
case prioritized = "Prioritized"
|
||||||
}
|
}
|
||||||
@ -19,12 +18,12 @@ class AudioDeviceManager: ObservableObject {
|
|||||||
private let logger = Logger(subsystem: "com.prakashjoshipax.voiceink", category: "AudioDeviceManager")
|
private let logger = Logger(subsystem: "com.prakashjoshipax.voiceink", category: "AudioDeviceManager")
|
||||||
@Published var availableDevices: [(id: AudioDeviceID, uid: String, name: String)] = []
|
@Published var availableDevices: [(id: AudioDeviceID, uid: String, name: String)] = []
|
||||||
@Published var selectedDeviceID: AudioDeviceID?
|
@Published var selectedDeviceID: AudioDeviceID?
|
||||||
@Published var inputMode: AudioInputMode = .systemDefault
|
@Published var inputMode: AudioInputMode = .custom
|
||||||
@Published var prioritizedDevices: [PrioritizedDevice] = []
|
@Published var prioritizedDevices: [PrioritizedDevice] = []
|
||||||
var fallbackDeviceID: AudioDeviceID?
|
var fallbackDeviceID: AudioDeviceID?
|
||||||
|
|
||||||
var isRecordingActive: Bool = false
|
var isRecordingActive: Bool = false
|
||||||
|
|
||||||
static let shared = AudioDeviceManager()
|
static let shared = AudioDeviceManager()
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@ -33,14 +32,35 @@ class AudioDeviceManager: ObservableObject {
|
|||||||
loadAvailableDevices { [weak self] in
|
loadAvailableDevices { [weak self] in
|
||||||
self?.initializeSelectedDevice()
|
self?.initializeSelectedDevice()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
migrateFromSystemDefaultIfNeeded()
|
||||||
|
|
||||||
if let savedMode = UserDefaults.standard.audioInputModeRawValue,
|
if let savedMode = UserDefaults.standard.audioInputModeRawValue,
|
||||||
let mode = AudioInputMode(rawValue: savedMode) {
|
let mode = AudioInputMode(rawValue: savedMode) {
|
||||||
inputMode = mode
|
inputMode = mode
|
||||||
|
} else {
|
||||||
|
inputMode = .custom
|
||||||
}
|
}
|
||||||
|
|
||||||
setupDeviceChangeNotifications()
|
setupDeviceChangeNotifications()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func migrateFromSystemDefaultIfNeeded() {
|
||||||
|
if let savedModeRaw = UserDefaults.standard.audioInputModeRawValue,
|
||||||
|
savedModeRaw == "System Default" {
|
||||||
|
logger.info("Migrating from System Default mode to Custom mode")
|
||||||
|
|
||||||
|
if let fallbackID = fallbackDeviceID {
|
||||||
|
selectedDeviceID = fallbackID
|
||||||
|
if let device = availableDevices.first(where: { $0.id == fallbackID }) {
|
||||||
|
UserDefaults.standard.selectedAudioDeviceUID = device.uid
|
||||||
|
logger.info("Migrated to Custom mode with device: \(device.name)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UserDefaults.standard.audioInputModeRawValue = AudioInputMode.custom.rawValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func setupFallbackDevice() {
|
func setupFallbackDevice() {
|
||||||
let deviceID: AudioDeviceID? = getDeviceProperty(
|
let deviceID: AudioDeviceID? = getDeviceProperty(
|
||||||
@ -216,6 +236,14 @@ class AudioDeviceManager: ObservableObject {
|
|||||||
self.selectedDeviceID = id
|
self.selectedDeviceID = id
|
||||||
UserDefaults.standard.selectedAudioDeviceUID = uid
|
UserDefaults.standard.selectedAudioDeviceUID = uid
|
||||||
self.logger.info("Device selection saved with UID: \(uid)")
|
self.logger.info("Device selection saved with UID: \(uid)")
|
||||||
|
|
||||||
|
do {
|
||||||
|
try AudioDeviceConfiguration.setDefaultInputDevice(id)
|
||||||
|
self.logger.info("✅ Set device as system default immediately")
|
||||||
|
} catch {
|
||||||
|
self.logger.error("Failed to set device as system default: \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
|
||||||
self.notifyDeviceChange()
|
self.notifyDeviceChange()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -232,6 +260,14 @@ class AudioDeviceManager: ObservableObject {
|
|||||||
self.selectedDeviceID = id
|
self.selectedDeviceID = id
|
||||||
UserDefaults.standard.audioInputModeRawValue = AudioInputMode.custom.rawValue
|
UserDefaults.standard.audioInputModeRawValue = AudioInputMode.custom.rawValue
|
||||||
UserDefaults.standard.selectedAudioDeviceUID = uid
|
UserDefaults.standard.selectedAudioDeviceUID = uid
|
||||||
|
|
||||||
|
do {
|
||||||
|
try AudioDeviceConfiguration.setDefaultInputDevice(id)
|
||||||
|
self.logger.info("✅ Set device as system default immediately")
|
||||||
|
} catch {
|
||||||
|
self.logger.error("Failed to set device as system default: \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
|
||||||
self.notifyDeviceChange()
|
self.notifyDeviceChange()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -243,11 +279,8 @@ class AudioDeviceManager: ObservableObject {
|
|||||||
func selectInputMode(_ mode: AudioInputMode) {
|
func selectInputMode(_ mode: AudioInputMode) {
|
||||||
inputMode = mode
|
inputMode = mode
|
||||||
UserDefaults.standard.audioInputModeRawValue = mode.rawValue
|
UserDefaults.standard.audioInputModeRawValue = mode.rawValue
|
||||||
|
|
||||||
if mode == .systemDefault {
|
if selectedDeviceID == nil {
|
||||||
selectedDeviceID = nil
|
|
||||||
UserDefaults.standard.removeObject(forKey: UserDefaults.Keys.selectedAudioDeviceUID)
|
|
||||||
} else if selectedDeviceID == nil {
|
|
||||||
if inputMode == .custom {
|
if inputMode == .custom {
|
||||||
if let firstDevice = availableDevices.first {
|
if let firstDevice = availableDevices.first {
|
||||||
selectDevice(id: firstDevice.id)
|
selectDevice(id: firstDevice.id)
|
||||||
@ -255,15 +288,22 @@ class AudioDeviceManager: ObservableObject {
|
|||||||
} else if inputMode == .prioritized {
|
} else if inputMode == .prioritized {
|
||||||
selectHighestPriorityAvailableDevice()
|
selectHighestPriorityAvailableDevice()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if let currentDeviceID = selectedDeviceID {
|
||||||
|
do {
|
||||||
|
try AudioDeviceConfiguration.setDefaultInputDevice(currentDeviceID)
|
||||||
|
logger.info("✅ Set current device as system default when mode changed")
|
||||||
|
} catch {
|
||||||
|
logger.error("Failed to set device as system default: \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyDeviceChange()
|
notifyDeviceChange()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCurrentDevice() -> AudioDeviceID {
|
func getCurrentDevice() -> AudioDeviceID {
|
||||||
switch inputMode {
|
switch inputMode {
|
||||||
case .systemDefault:
|
|
||||||
return fallbackDeviceID ?? 0
|
|
||||||
case .custom:
|
case .custom:
|
||||||
if let id = selectedDeviceID, isDeviceAvailable(id) {
|
if let id = selectedDeviceID, isDeviceAvailable(id) {
|
||||||
return id
|
return id
|
||||||
@ -333,14 +373,15 @@ class AudioDeviceManager: ObservableObject {
|
|||||||
|
|
||||||
private func selectHighestPriorityAvailableDevice() {
|
private func selectHighestPriorityAvailableDevice() {
|
||||||
let sortedDevices = prioritizedDevices.sorted { $0.priority < $1.priority }
|
let sortedDevices = prioritizedDevices.sorted { $0.priority < $1.priority }
|
||||||
|
|
||||||
for device in sortedDevices {
|
for device in sortedDevices {
|
||||||
if let availableDevice = availableDevices.first(where: { $0.uid == device.id }) {
|
if let availableDevice = availableDevices.first(where: { $0.uid == device.id }) {
|
||||||
selectedDeviceID = availableDevice.id
|
selectedDeviceID = availableDevice.id
|
||||||
logger.info("Selected prioritized device: \(device.name) (Priority: \(device.priority))")
|
logger.info("Selected prioritized device: \(device.name) (Priority: \(device.priority))")
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try AudioDeviceConfiguration.setDefaultInputDevice(availableDevice.id)
|
try AudioDeviceConfiguration.setDefaultInputDevice(availableDevice.id)
|
||||||
|
logger.info("✅ Set prioritized device as system default immediately")
|
||||||
} catch {
|
} catch {
|
||||||
logger.error("Failed to set prioritized device: \(error.localizedDescription)")
|
logger.error("Failed to set prioritized device: \(error.localizedDescription)")
|
||||||
continue
|
continue
|
||||||
@ -349,7 +390,7 @@ class AudioDeviceManager: ObservableObject {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fallbackToDefaultDevice()
|
fallbackToDefaultDevice()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -278,8 +278,8 @@ struct OnboardingPermissionsView: View {
|
|||||||
// Check microphone permission
|
// Check microphone permission
|
||||||
permissionStates[0] = AVCaptureDevice.authorizationStatus(for: .audio) == .authorized
|
permissionStates[0] = AVCaptureDevice.authorizationStatus(for: .audio) == .authorized
|
||||||
|
|
||||||
// Check if device is selected or system default mode is being used
|
// Check if device is selected
|
||||||
permissionStates[1] = audioDeviceManager.selectedDeviceID != nil || audioDeviceManager.inputMode == .systemDefault
|
permissionStates[1] = audioDeviceManager.selectedDeviceID != nil
|
||||||
|
|
||||||
// Check accessibility permission
|
// Check accessibility permission
|
||||||
permissionStates[2] = AXIsProcessTrusted()
|
permissionStates[2] = AXIsProcessTrusted()
|
||||||
@ -315,7 +315,7 @@ struct OnboardingPermissionsView: View {
|
|||||||
audioDeviceManager.loadAvailableDevices()
|
audioDeviceManager.loadAvailableDevices()
|
||||||
|
|
||||||
if audioDeviceManager.availableDevices.isEmpty {
|
if audioDeviceManager.availableDevices.isEmpty {
|
||||||
audioDeviceManager.selectInputMode(.systemDefault)
|
audioDeviceManager.selectInputMode(.custom)
|
||||||
withAnimation {
|
withAnimation {
|
||||||
permissionStates[currentPermissionIndex] = true
|
permissionStates[currentPermissionIndex] = true
|
||||||
showAnimation = true
|
showAnimation = true
|
||||||
|
|||||||
@ -258,15 +258,13 @@ struct InputModeCard: View {
|
|||||||
|
|
||||||
private var icon: String {
|
private var icon: String {
|
||||||
switch mode {
|
switch mode {
|
||||||
case .systemDefault: return "macbook.and.iphone"
|
|
||||||
case .custom: return "mic.circle.fill"
|
case .custom: return "mic.circle.fill"
|
||||||
case .prioritized: return "list.number"
|
case .prioritized: return "list.number"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var description: String {
|
private var description: String {
|
||||||
switch mode {
|
switch mode {
|
||||||
case .systemDefault: return "Use system's default input device"
|
|
||||||
case .custom: return "Select a specific input device"
|
case .custom: return "Select a specific input device"
|
||||||
case .prioritized: return "Set up device priority order"
|
case .prioritized: return "Set up device priority order"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user