From 1d8a8919d23b65f27d709dec6d96c192746585d6 Mon Sep 17 00:00:00 2001 From: Vincent Neo <23420208+vincentneo@users.noreply.github.com> Date: Thu, 7 Dec 2023 23:38:37 +0800 Subject: [PATCH] Option to run script when sample rate change --- Quality/AppDelegate.swift | 37 +++++++++++++++++++++++++++++++++++++ Quality/Defaults.swift | 10 ++++++++++ Quality/OutputDevices.swift | 19 +++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/Quality/AppDelegate.swift b/Quality/AppDelegate.swift index 03d157c..7abf513 100644 --- a/Quality/AppDelegate.swift +++ b/Quality/AppDelegate.swift @@ -22,6 +22,8 @@ class AppDelegate: NSObject, NSApplicationDelegate { var statusItem: NSStatusItem? var cancellable: AnyCancellable? + + var currentScriptSelectionMenuItem: NSMenuItem? private var _statusItemTitle = "Loading..." var statusItemTitle: String { @@ -62,6 +64,8 @@ class AppDelegate: NSObject, NSApplicationDelegate { checkPermissions() let menu = NSMenu() + + menu.delegate = self let sampleRateView = ContentView().environmentObject(outputDevices) let view = NSHostingView(rootView: sampleRateView) @@ -96,6 +100,17 @@ class AppDelegate: NSObject, NSApplicationDelegate { aboutItem.submenu?.addItem(buildItem) menu.addItem(aboutItem) + let scriptMenu = NSMenuItem(title: "Scripting", action: nil, keyEquivalent: "") + let selectScript = NSMenuItem(title: "Select Script...", action: #selector(selectScript(_:)), keyEquivalent: "") + let resetScript = NSMenuItem(title: "Clear selection", action: #selector(resetScript(_:)), keyEquivalent: "") + let currentScriptSelectionMenuItem = NSMenuItem(title: "No selection", action: nil, keyEquivalent: "") + self.currentScriptSelectionMenuItem = currentScriptSelectionMenuItem + scriptMenu.submenu = NSMenu() + scriptMenu.submenu?.addItem(selectScript) + scriptMenu.submenu?.addItem(resetScript) + scriptMenu.submenu?.addItem(currentScriptSelectionMenuItem) + menu.addItem(scriptMenu) + let quitItem = NSMenuItem(title: "Quit", action: #selector(NSApp.terminate(_:)), keyEquivalent: "") menu.addItem(quitItem) @@ -175,4 +190,26 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } + @objc func selectScript(_ item: NSMenuItem) { + let panel = NSOpenPanel() + panel.canChooseFiles = true + panel.canChooseDirectories = false + panel.allowsMultipleSelection = false + panel.message = "Select a script that should be invoked when sample rate changes." + + panel.begin { response in + Defaults.shared.shellScriptPath = panel.url?.path + } + } + + @objc func resetScript(_ item: NSMenuItem) { + Defaults.shared.shellScriptPath = nil + } + +} + +extension AppDelegate: NSMenuDelegate { + func menuWillOpen(_ menu: NSMenu) { + currentScriptSelectionMenuItem?.title = Defaults.shared.shellScriptPath ?? "No selection" + } } diff --git a/Quality/Defaults.swift b/Quality/Defaults.swift index fc0d5d4..a31ad76 100644 --- a/Quality/Defaults.swift +++ b/Quality/Defaults.swift @@ -12,6 +12,7 @@ class Defaults: ObservableObject { private let kUserPreferIconStatusBarItem = "com.vincent-neo.LosslessSwitcher-Key-UserPreferIconStatusBarItem" private let kSelectedDeviceUID = "com.vincent-neo.LosslessSwitcher-Key-SelectedDeviceUID" private let kUserPreferBitDepthDetection = "com.vincent-neo.LosslessSwitcher-Key-BitDepthDetection" + private let kShellScriptPath = "KeyShellScriptPath" private init() { UserDefaults.standard.register(defaults: [ @@ -40,6 +41,15 @@ class Defaults: ObservableObject { } } + var shellScriptPath: String? { + get { + return UserDefaults.standard.string(forKey: kShellScriptPath) + } + set { + UserDefaults.standard.setValue(newValue, forKey: kShellScriptPath) + } + } + @Published var userPreferBitDepthDetection: Bool diff --git a/Quality/OutputDevices.swift b/Quality/OutputDevices.swift index 1773cd1..78357ff 100644 --- a/Quality/OutputDevices.swift +++ b/Quality/OutputDevices.swift @@ -252,5 +252,24 @@ class OutputDevices: ObservableObject { let delegate = AppDelegate.instance delegate?.statusItemTitle = String(format: "%.1f kHz", readableSampleRate) } + self.runUserScript(sampleRate) + } + + func runUserScript(_ sampleRate: Float64) { + guard let scriptPath = Defaults.shared.shellScriptPath else { return } + let argumentSampleRate = String(Int(sampleRate)) + Task.detached { + let scriptURL = URL(fileURLWithPath: scriptPath) + do { + let task = try NSUserUnixTask(url: scriptURL) + let arguments = [ + argumentSampleRate + ] + try await task.execute(withArguments: arguments) + } + catch { + print("TASK ERR \(error)") + } + } } }