Skip to content

Commit

Permalink
Implement notification
Browse files Browse the repository at this point in the history
  • Loading branch information
viettrungphan committed Apr 27, 2021
1 parent a1cb99c commit 4f44a7e
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 22 deletions.
4 changes: 4 additions & 0 deletions Micro Sniff/Micro Sniff.xcodeproj/project.pbxproj
Expand Up @@ -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 */
Expand Down Expand Up @@ -115,6 +116,7 @@
550151DC23FA41D7007D6568 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
550151DE23FA41D7007D6568 /* info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = info.plist; sourceTree = "<group>"; };
550151DF23FA41D7007D6568 /* MicroSniff.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MicroSniff.entitlements; sourceTree = "<group>"; };
55ACE6172633C2560081883B /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -295,6 +297,7 @@
0879E9C324065A06007890BC /* Util.swift */,
08A8B81323FA8100009C541C /* AMCoreAudio */,
0837EB8824099C980092C830 /* Preference.swift */,
55ACE6172633C2560081883B /* NotificationManager.swift */,
);
path = Helper;
sourceTree = "<group>";
Expand Down Expand Up @@ -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 */,
Expand Down
Expand Up @@ -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.
Expand Down
40 changes: 28 additions & 12 deletions Micro Sniff/Micro Sniff/Helper/MicroManager.swift
Expand Up @@ -14,6 +14,8 @@ class MicroManager {
private init(){}

var microDidRunningSomeWhere: ((_ isRunning: Bool,_ title: String) -> ())?
var microDidAdd:((_ title: String) ->())?
var microDidRemove:((_ title: String) ->())?


func regisAudioNotification() {
Expand All @@ -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
}
}
}

Expand Down
22 changes: 22 additions & 0 deletions Micro Sniff/Micro Sniff/Helper/NotificationManager.swift
Expand Up @@ -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)
}


}
22 changes: 22 additions & 0 deletions Micro Sniff/Micro Sniff/Helper/Preference.swift
Expand Up @@ -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"
}
}

Expand Down Expand Up @@ -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)
Expand Down
10 changes: 9 additions & 1 deletion Micro Sniff/Micro Sniff/StatusBarController.swift
Expand Up @@ -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) {
Expand Down
Expand Up @@ -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()

Expand All @@ -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) {
Expand Down Expand Up @@ -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
}

}
@@ -1,13 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="17701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17701"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="GeneralPreferenceViewController" customModule="MicMonitor" customModuleProvider="target">
<customObject id="-2" userLabel="File's Owner" customClass="GeneralPreferenceViewController" customModule="Micro_Sniff" customModuleProvider="target">
<connections>
<outlet property="checkBoxEnableNotificationSound" destination="MbV-iT-K0X" id="mo5-d3-Qja"/>
<outlet property="checkboxEnableNotification" destination="AVW-S5-pqK" id="t2u-2O-jVl"/>
<outlet property="checkboxKeepIconInDock" destination="eVh-Mm-0g0" id="S9b-Yg-3yr"/>
<outlet property="checkboxShowPreferencesOnLaunch" destination="yTT-zQ-e5q" id="sEy-J5-E0U"/>
<outlet property="checkboxStartAtLogin" destination="GvI-Om-HDr" id="t4U-PS-IpH"/>
Expand All @@ -17,13 +19,13 @@
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<view wantsLayer="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0Zx-QX-MJo">
<rect key="frame" x="0.0" y="0.0" width="470" height="177"/>
<rect key="frame" x="0.0" y="0.0" width="475" height="177"/>
<subviews>
<stackView distribution="fill" orientation="vertical" alignment="leading" spacing="10" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0n4-q2-b0q">
<rect key="frame" x="219" y="58" width="191" height="62"/>
<rect key="frame" x="219" y="29" width="196" height="120"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="GvI-Om-HDr">
<rect key="frame" x="-2" y="46" width="170" height="18"/>
<rect key="frame" x="-2" y="103" width="174" height="18"/>
<buttonCell key="cell" type="check" title="Start Micro Sniff at login" bezelStyle="regularSquare" imagePosition="left" inset="2" id="bf5-e5-tnZ">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -33,7 +35,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="yTT-zQ-e5q">
<rect key="frame" x="-2" y="22" width="194" height="18"/>
<rect key="frame" x="-2" y="77" width="198" height="18"/>
<buttonCell key="cell" type="check" title="Show preferences on launch" bezelStyle="regularSquare" imagePosition="left" inset="2" id="9pC-z6-4yp">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -43,7 +45,7 @@
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="eVh-Mm-0g0">
<rect key="frame" x="-2" y="-2" width="130" height="18"/>
<rect key="frame" x="-2" y="51" width="134" height="18"/>
<buttonCell key="cell" type="check" title="Keep icon in dock" bezelStyle="regularSquare" imagePosition="left" inset="2" id="ymJ-QM-wIJ">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
Expand All @@ -52,16 +54,40 @@
<action selector="toggleKeepIconInDock:" target="-2" id="zjN-ZB-LcL"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="AVW-S5-pqK">
<rect key="frame" x="-2" y="25" width="139" height="18"/>
<buttonCell key="cell" type="check" title="Enable notification" bezelStyle="regularSquare" imagePosition="left" inset="2" id="9f9-rr-bYS">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleEnableNotification:" target="-2" id="KdM-d7-zpa"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="MbV-iT-K0X">
<rect key="frame" x="-2" y="-1" width="180" height="18"/>
<buttonCell key="cell" type="check" title="Enable notification sound" bezelStyle="regularSquare" imagePosition="left" inset="2" id="bnV-9C-q5P">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="toggleEnableNotificationSound:" target="-2" id="1CJ-Li-g8B"/>
</connections>
</button>
</subviews>
<visibilityPriorities>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
<integer value="1000"/>
</visibilityPriorities>
<customSpacing>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
<real value="3.4028234663852886e+38"/>
</customSpacing>
</stackView>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="yhD-2X-r8G">
Expand Down

0 comments on commit 4f44a7e

Please sign in to comment.