diff --git a/Micro Sniff/Micro Sniff.xcodeproj/project.pbxproj b/Micro Sniff/Micro Sniff.xcodeproj/project.pbxproj index 7d8354d..8c99942 100644 --- a/Micro Sniff/Micro Sniff.xcodeproj/project.pbxproj +++ b/Micro Sniff/Micro Sniff.xcodeproj/project.pbxproj @@ -50,6 +50,7 @@ 550151D623FA41D5007D6568 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 550151D523FA41D5007D6568 /* AppDelegate.swift */; }; 550151DA23FA41D7007D6568 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 550151D923FA41D7007D6568 /* Assets.xcassets */; }; 550151DD23FA41D7007D6568 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 550151DB23FA41D7007D6568 /* Main.storyboard */; }; + 55ACE6182633C2560081883B /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55ACE6172633C2560081883B /* NotificationManager.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -115,6 +116,7 @@ 550151DC23FA41D7007D6568 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 550151DE23FA41D7007D6568 /* info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = info.plist; sourceTree = ""; }; 550151DF23FA41D7007D6568 /* MicroSniff.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MicroSniff.entitlements; sourceTree = ""; }; + 55ACE6172633C2560081883B /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -295,6 +297,7 @@ 0879E9C324065A06007890BC /* Util.swift */, 08A8B81323FA8100009C541C /* AMCoreAudio */, 0837EB8824099C980092C830 /* Preference.swift */, + 55ACE6172633C2560081883B /* NotificationManager.swift */, ); path = Helper; sourceTree = ""; @@ -468,6 +471,7 @@ 08A8B83A23FA8100009C541C /* AudioHardwareEvent.swift in Sources */, 08A8B83E23FA8100009C541C /* BundleInfo.swift in Sources */, 08A8B83123FA8100009C541C /* AudioObject+Helpers.swift in Sources */, + 55ACE6182633C2560081883B /* NotificationManager.swift in Sources */, 08B509072409921600F4FB4F /* Bundle+Extension.swift in Sources */, 086553682408DEA000715BEB /* GeneralPreferenceViewController.swift in Sources */, 08A8B84423FA863A009C541C /* StatusBarController.swift in Sources */, diff --git a/Micro Sniff/Micro Sniff/Helper/AMCoreAudio/Public/AudioDevice.swift b/Micro Sniff/Micro Sniff/Helper/AMCoreAudio/Public/AudioDevice.swift index eaa3b04..658da7b 100644 --- a/Micro Sniff/Micro Sniff/Helper/AMCoreAudio/Public/AudioDevice.swift +++ b/Micro Sniff/Micro Sniff/Helper/AMCoreAudio/Public/AudioDevice.swift @@ -211,7 +211,9 @@ public final class AudioDevice: AudioObject { public class func allInputDevices() -> [AudioDevice] { return allDevices().filter { $0.channels(direction: .recording) > 0 } } - + public func isMicroDevice() -> Bool { + channels(direction: .recording) > 0 + } /// All the devices in the system that have at least one output. /// /// - Note: The list may also include *Aggregate* and *Multi-Output* devices. diff --git a/Micro Sniff/Micro Sniff/Helper/MicroManager.swift b/Micro Sniff/Micro Sniff/Helper/MicroManager.swift index 5d26127..225cfdd 100644 --- a/Micro Sniff/Micro Sniff/Helper/MicroManager.swift +++ b/Micro Sniff/Micro Sniff/Helper/MicroManager.swift @@ -14,6 +14,8 @@ class MicroManager { private init(){} var microDidRunningSomeWhere: ((_ isRunning: Bool,_ title: String) -> ())? + var microDidAdd:((_ title: String) ->())? + var microDidRemove:((_ title: String) ->())? func regisAudioNotification() { @@ -29,19 +31,33 @@ class MicroManager { } extension MicroManager: EventSubscriber { func eventReceiver(_ event: Event) { - guard let event = event as? AudioDeviceEvent else { return } - - switch event { - - case .isRunningSomewhereDidChange(audioDevice: let audioDevice): - guard - audioDevice.isInputOnlyDevice(), - let microDidRunningSomeWhere = self.microDidRunningSomeWhere - else {return} - - microDidRunningSomeWhere(audioDevice.isRunningSomewhere(), audioDevice.name) + if let event = event as? AudioDeviceEvent { + switch event { + case .isRunningSomewhereDidChange(audioDevice: let audioDevice): + guard + audioDevice.isInputOnlyDevice(), + let microDidRunningSomeWhere = self.microDidRunningSomeWhere + else {return} + microDidRunningSomeWhere(audioDevice.isRunningSomewhere(), audioDevice.name) + default: break + + } + } - default: break + if let event = event as? AudioHardwareEvent { + switch event { + case .deviceListChanged(addedDevices: let addedDevices, removedDevices: let removedDevices): + + if let microDidAdd = self.microDidAdd, let addedMic = addedDevices.first(where: {$0.isMicroDevice()}) { + microDidAdd(addedMic.name) + } + + if let microDidRemove = microDidRemove, let removedMic = removedDevices.first(where: {$0.isMicroDevice()}) { + microDidRemove(removedMic.name) + } + + default: break + } } } diff --git a/Micro Sniff/Micro Sniff/Helper/NotificationManager.swift b/Micro Sniff/Micro Sniff/Helper/NotificationManager.swift index fc7d9ac..0259ca4 100644 --- a/Micro Sniff/Micro Sniff/Helper/NotificationManager.swift +++ b/Micro Sniff/Micro Sniff/Helper/NotificationManager.swift @@ -7,3 +7,25 @@ // import Foundation + +class NotificationManager { + + static private func showNotification(title: String, desc: String, sound: Bool) { + let notification = NSUserNotification() + notification.title = title + notification.subtitle = desc + if sound { + notification.soundName = NSUserNotificationDefaultSoundName + } + notification.deliveryDate = Date(timeIntervalSinceNow: 1) + + NSUserNotificationCenter.default.deliver(notification) + } + + static func showNotificationIfEnable(title: String, desc: String) { + if !Preference.isShowNotification {return} + self.showNotification(title: title, desc: desc, sound: Preference.isEnableNotificationSound) + } + + +} diff --git a/Micro Sniff/Micro Sniff/Helper/Preference.swift b/Micro Sniff/Micro Sniff/Helper/Preference.swift index d3840f0..2c84b42 100644 --- a/Micro Sniff/Micro Sniff/Helper/Preference.swift +++ b/Micro Sniff/Micro Sniff/Helper/Preference.swift @@ -13,6 +13,8 @@ extension UserDefaults { static let startAtLogin = "startAtLogin" static let dockIconState = "dockIconState" static let showPreferencesOnLaunch = "showPreferencesOnLaunch" + static let isEnableNotificationSound = "isEnableNotificationSound" + static let isShowNotification = "isShowNotification" } } @@ -44,6 +46,26 @@ enum Preference { } } + static var isShowNotification: Bool { + get { + return UserDefaults.standard.bool(forKey: UserDefaults.Key.isShowNotification) + } + + set { + UserDefaults.standard.set(newValue, forKey: UserDefaults.Key.isShowNotification) + } + } + + static var isEnableNotificationSound: Bool { + get { + return UserDefaults.standard.bool(forKey: UserDefaults.Key.isEnableNotificationSound) + } + + set { + UserDefaults.standard.set(newValue, forKey: UserDefaults.Key.isEnableNotificationSound) + } + } + static var showPreferencesOnlaunch: Bool { get { return UserDefaults.standard.bool(forKey: UserDefaults.Key.showPreferencesOnLaunch) diff --git a/Micro Sniff/Micro Sniff/StatusBarController.swift b/Micro Sniff/Micro Sniff/StatusBarController.swift index 4438723..1bf9bc0 100644 --- a/Micro Sniff/Micro Sniff/StatusBarController.swift +++ b/Micro Sniff/Micro Sniff/StatusBarController.swift @@ -37,14 +37,22 @@ class StatusBarController { if let mic = AudioDevice.allInputDevices().first(where: {$0.isRunningSomewhere()}) { createAndShowWindow(micTitle: mic.name) } - + MicroManager.sharedInstance.microDidRunningSomeWhere = {[weak self] (isRunning, title) in + NotificationManager.showNotificationIfEnable(title: title, desc: "\(title) \(isRunning ? "running" : "stopped")") if isRunning { self?.createAndShowWindow(micTitle: title) } else { self?.removeWindow() } } + + MicroManager.sharedInstance.microDidAdd = {deviceName in + NotificationManager.showNotificationIfEnable(title: deviceName, desc: "\(deviceName) connected") + } + MicroManager.sharedInstance.microDidRemove = {deviceName in + NotificationManager.showNotificationIfEnable(title: deviceName, desc: "\(deviceName) disconnected") + } } private func createAndShowWindow(micTitle: String) { diff --git a/Micro Sniff/Micro Sniff/Views/Preferences/General/GeneralPreferenceViewController.swift b/Micro Sniff/Micro Sniff/Views/Preferences/General/GeneralPreferenceViewController.swift index d48edc1..fc306d2 100644 --- a/Micro Sniff/Micro Sniff/Views/Preferences/General/GeneralPreferenceViewController.swift +++ b/Micro Sniff/Micro Sniff/Views/Preferences/General/GeneralPreferenceViewController.swift @@ -20,6 +20,10 @@ final class GeneralPreferenceViewController: NSViewController, PreferencePane { @IBOutlet weak var checkboxKeepIconInDock: NSButton! @IBOutlet weak var checkboxShowPreferencesOnLaunch: NSButton! + @IBOutlet weak var checkboxEnableNotification: NSButton! + + @IBOutlet weak var checkBoxEnableNotificationSound: NSButton! + override func viewDidLoad() { super.viewDidLoad() @@ -30,6 +34,7 @@ final class GeneralPreferenceViewController: NSViewController, PreferencePane { checkboxStartAtLogin.state = Preference.startAtLogin ? .on : .off checkboxKeepIconInDock.state = Preference.dockIconState == .show ? .on : .off checkboxShowPreferencesOnLaunch.state = Preference.showPreferencesOnlaunch ? .on : .off + checkboxEnableNotification.state = Preference.isShowNotification ? .on : .off } @IBAction func toggleStartAtLogin(_ sender: NSButton) { @@ -64,4 +69,12 @@ final class GeneralPreferenceViewController: NSViewController, PreferencePane { break } } + + @IBAction func toggleEnableNotification(_ sender: NSButton) { + Preference.isShowNotification = sender.state == .on + } + @IBAction func toggleEnableNotificationSound(_ sender: NSButton) { + Preference.isEnableNotificationSound = sender.state == .on + } + } diff --git a/Micro Sniff/Micro Sniff/Views/Preferences/General/GeneralPreferenceViewController.xib b/Micro Sniff/Micro Sniff/Views/Preferences/General/GeneralPreferenceViewController.xib index a3635b6..9584f92 100644 --- a/Micro Sniff/Micro Sniff/Views/Preferences/General/GeneralPreferenceViewController.xib +++ b/Micro Sniff/Micro Sniff/Views/Preferences/General/GeneralPreferenceViewController.xib @@ -1,13 +1,15 @@ - + - + - + + + @@ -17,13 +19,13 @@ - + - + + + + + + +