Isaac: Use customized beep sound & fart sound

- Initially written by Shiki, rewritten by Isaac to address the issue with duplicated NSSound instances.

Co-Authored-By: ix4n33 <16833681+isaacxen@users.noreply.github.com>
This commit is contained in:
ShikiSuen 2022-01-16 22:48:18 +08:00
parent fe9b8c7332
commit 6c15845178
12 changed files with 152 additions and 15 deletions

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="19529" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19529"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -218,17 +217,17 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Yaj-QY-7xV">
<rect key="frame" x="19" y="102.5" width="423" height="17"/>
<rect key="frame" x="19" y="103.5" width="423" height="17"/>
<constraints>
<constraint firstAttribute="height" constant="16" id="doD-85-k80"/>
<constraint firstAttribute="height" constant="16" id="Pfc-tS-s5a"/>
</constraints>
<buttonCell key="cell" type="check" title="Enable partial CNS11643 Support (non-PUA UTF-8 characters only)" bezelStyle="regularSquare" imagePosition="left" controlSize="small" inset="2" id="W24-T4-cg0">
<buttonCell key="cell" type="check" title="Enable CNS11643 Support (non-PUA UTF-8 characters only)" bezelStyle="regularSquare" imagePosition="left" controlSize="small" inset="2" id="W24-T4-cg0">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="cellTitle"/>
</buttonCell>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5IL-zZ-CL9">
<rect key="frame" x="19" y="81.5" width="423" height="16"/>
<rect key="frame" x="19" y="82.5" width="423" height="16"/>
<buttonCell key="cell" type="check" title="Auto-convert traditional Chinese glyphs to KangXi characters" bezelStyle="regularSquare" imagePosition="left" controlSize="small" inset="2" id="BSK-bH-Gct">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="cellTitle"/>
@ -237,14 +236,28 @@
<binding destination="32" name="value" keyPath="values.ChineseConversionEnabled" id="X0A-OC-T6e"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="mzw-F2-aAQ">
<rect key="frame" x="19" y="61.5" width="423" height="16"/>
<buttonCell key="cell" type="check" title="Stop farting (when typed phonetic combination is invalid, etc.)" bezelStyle="regularSquare" imagePosition="left" controlSize="small" inset="2" id="ArK-Vk-OoT">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="cellTitle"/>
</buttonCell>
<connections>
<action selector="clickedWhetherIMEShouldNotFartToggleAction:" target="-1" id="ieE-Xb-JtL"/>
<binding destination="32" name="value" keyPath="values.ShouldNotFartInLieuOfBeep" id="7Of-X3-D03"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="Yaj-QY-7xV" secondAttribute="trailing" constant="20" symbolic="YES" id="1cK-ql-tUm"/>
<constraint firstItem="5IL-zZ-CL9" firstAttribute="top" secondItem="Yaj-QY-7xV" secondAttribute="bottom" constant="6" symbolic="YES" id="GNJ-3b-BdS"/>
<constraint firstItem="Yaj-QY-7xV" firstAttribute="leading" secondItem="brd-6J-saN" secondAttribute="leading" constant="20" symbolic="YES" id="Osh-Ld-41D"/>
<constraint firstItem="Yaj-QY-7xV" firstAttribute="trailing" secondItem="5IL-zZ-CL9" secondAttribute="trailing" id="aV1-VZ-dv0"/>
<constraint firstItem="Yaj-QY-7xV" firstAttribute="top" secondItem="brd-6J-saN" secondAttribute="top" constant="15" id="p4L-Wx-dK0"/>
<constraint firstItem="Yaj-QY-7xV" firstAttribute="leading" secondItem="5IL-zZ-CL9" secondAttribute="leading" id="r7K-Wg-s9D"/>
<constraint firstItem="5IL-zZ-CL9" firstAttribute="leading" secondItem="mzw-F2-aAQ" secondAttribute="leading" id="1Ly-qx-Gu3"/>
<constraint firstItem="Yaj-QY-7xV" firstAttribute="top" secondItem="brd-6J-saN" secondAttribute="top" constant="14.5" id="3t1-EX-nuL"/>
<constraint firstItem="5IL-zZ-CL9" firstAttribute="top" secondItem="Yaj-QY-7xV" secondAttribute="bottom" constant="6" symbolic="YES" id="MeX-CD-9FN"/>
<constraint firstItem="Yaj-QY-7xV" firstAttribute="trailing" secondItem="5IL-zZ-CL9" secondAttribute="trailing" id="S0v-Op-wDh"/>
<constraint firstAttribute="trailing" secondItem="Yaj-QY-7xV" secondAttribute="trailing" constant="20" symbolic="YES" id="UKC-jH-d9A"/>
<constraint firstItem="Yaj-QY-7xV" firstAttribute="leading" secondItem="brd-6J-saN" secondAttribute="leading" constant="20" symbolic="YES" id="YeI-ie-7B9"/>
<constraint firstItem="mzw-F2-aAQ" firstAttribute="top" secondItem="5IL-zZ-CL9" secondAttribute="bottom" constant="6" symbolic="YES" id="hC7-fa-qhc"/>
<constraint firstItem="Yaj-QY-7xV" firstAttribute="leading" secondItem="5IL-zZ-CL9" secondAttribute="leading" id="tjY-PG-4Kz"/>
<constraint firstItem="5IL-zZ-CL9" firstAttribute="trailing" secondItem="mzw-F2-aAQ" secondAttribute="trailing" id="xg7-MH-hSW"/>
</constraints>
</view>
</box>

BIN
Source/Beep.aif Normal file

Binary file not shown.

View File

@ -0,0 +1,74 @@
//
// clsSFX.swift
//
// Copyright (c) 2021-2022 The vChewing Project.
//
// Contributors:
// Shiki Suen (@ShikiSuen) @ vChewing
// Isaac Xen a.k.a. ix4n33 (@IsaacXen) @ no affiliation
//
// Based on the Syrup Project and the Formosana Library
// by Lukhnos Liu (@lukhnos).
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
import Cocoa
@objc public class clsSFX: NSObject, NSSoundDelegate {
private static let shared = clsSFX()
private override init(){
super.init()
}
private var currentBeep: NSSound?
private func beep() {
// Stop existing beep
if let beep = currentBeep {
if beep.isPlaying {
beep.stop()
}
}
// Create a new beep sound if possible
var sndBeep:String
if Preferences.shouldNotFartInLieuOfBeep == false {
sndBeep = "Fart"
} else {
sndBeep = "Beep"
}
guard
let beep = NSSound(named:sndBeep)
else {
NSSound.beep()
return
}
beep.delegate = self
beep.volume = 0.4
beep.play()
currentBeep = beep
}
@objc public func sound(_ sound: NSSound, didFinishPlaying flag: Bool) {
currentBeep = nil
}
@objc static func beep() {
shared.beep()
}
}

View File

@ -33,6 +33,7 @@
import Cocoa
private let kShouldNotFartInLieuOfBeep = "ShouldNotFartInLieuOfBeep"
private let kCheckUpdateAutomatically = "CheckUpdateAutomatically"
private let kCandidateListTextSize = "CandidateListTextSize"
private let kChooseCandidateUsingSpaceKey = "ChooseCandidateUsingSpaceKey"
@ -75,6 +76,11 @@ private let kChineseConversionEnabledKey = "ChineseConversionEnabled"
if UserDefaults.standard.object(forKey: kChineseConversionEnabledKey) == nil {
UserDefaults.standard.set(Preferences.chineseConversionEnabled, forKey: kChineseConversionEnabledKey)
}
//
if UserDefaults.standard.object(forKey: kShouldNotFartInLieuOfBeep) == nil {
UserDefaults.standard.set(Preferences.shouldNotFartInLieuOfBeep, forKey: kShouldNotFartInLieuOfBeep)
}
UserDefaults.standard.synchronize()
}

BIN
Source/Fart.aif Normal file

Binary file not shown.

View File

@ -489,8 +489,8 @@ NS_INLINE size_t max(size_t a, size_t b) { return a > b ? a : b; }
- (void)beep
{
// use the system's default sound (configurable in System Preferences) to give a warning
NSBeep();
// use the vChewing beep.
[clsSFX beep];
}
- (string)_currentLayout

View File

@ -45,6 +45,7 @@ private let kChooseCandidateUsingSpaceKey = "ChooseCandidateUsingSpaceKey"
private let kChineseConversionEnabledKey = "ChineseConversionEnabled"
private let kHalfWidthPunctuationEnabledKey = "HalfWidthPunctuationEnable"
private let kEscToCleanInputBufferKey = "EscToCleanInputBuffer"
private let kShouldNotFartInLieuOfBeep = "ShouldNotFartInLieuOfBeep"
private let kCandidateTextFontName = "CandidateTextFontName"
private let kCandidateKeyLabelFontName = "CandidateKeyLabelFontName"
@ -245,6 +246,15 @@ struct ComposingKeys {
@UserDefault(key: kChooseCandidateUsingSpaceKey, defaultValue: true)
@objc static var chooseCandidateUsingSpace: Bool
@UserDefault(key: kShouldNotFartInLieuOfBeep, defaultValue: true)
@objc static var shouldNotFartInLieuOfBeep: Bool
@objc static func toggleShouldNotFartInLieuOfBeep() -> Bool {
shouldNotFartInLieuOfBeep = !shouldNotFartInLieuOfBeep
UserDefaults.standard.set(shouldNotFartInLieuOfBeep, forKey: kShouldNotFartInLieuOfBeep)
return shouldNotFartInLieuOfBeep
}
@UserDefault(key: kChineseConversionEnabledKey, defaultValue: false)
@objc static var chineseConversionEnabled: Bool

View File

@ -51,6 +51,7 @@ extension RangeReplaceableCollection where Element: Hashable {
@IBOutlet weak var fontSizePopUpButton: NSPopUpButton!
@IBOutlet weak var basisKeyboardLayoutButton: NSPopUpButton!
@IBOutlet weak var selectionKeyComboBox: NSComboBox!
@IBOutlet weak var clickedWhetherIMEShouldNotFartToggle: NSButton!
override func awakeFromNib() {
let list = TISCreateInputSourceList(nil, true).takeRetainedValue() as! [TISInputSource]
@ -151,12 +152,16 @@ extension RangeReplaceableCollection where Element: Hashable {
}
}
@IBAction func clickedWhetherIMEShouldNotFartToggleAction(_ sender: Any) {
clsSFX.beep()
}
@IBAction func changeSelectionKeyAction(_ sender: Any) {
let keys = (sender as AnyObject).stringValue.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines).charDeDuplicate
if keys.count != 9 || !keys.canBeConverted(to: .ascii) {
selectionKeyComboBox.stringValue = Preferences.defaultKeys
Preferences.candidateKeys = Preferences.defaultKeys // nil
NSSound.beep()
clsSFX.beep()
return
}

View File

@ -101,6 +101,9 @@
/* Class = "NSTextFieldCell"; title = "UI language setting:"; ObjectID = "9DS-Rc-TXq"; */
"9DS-Rc-TXq.title" = "UI language setting:";
/* Class = "NSButtonCell"; title = "Stop farting (when typed phonetic combination is invalid, etc.)"; ObjectID = "ArK-Vk-OoT"; */
"ArK-Vk-OoT.title" = "Stop farting (when typed phonetic combination is invalid, etc.)";
/* Class = "NSButtonCell"; title = "Auto-convert traditional Chinese glyphs to KangXi characters"; ObjectID = "BSK-bH-Gct"; */
"BSK-bH-Gct.title" = "Auto-convert traditional Chinese glyphs to KangXi characters";

View File

@ -101,6 +101,9 @@
/* Class = "NSTextFieldCell"; title = "UI language setting:"; ObjectID = "9DS-Rc-TXq"; */
"9DS-Rc-TXq.title" = "介面语言设定:";
/* Class = "NSButtonCell"; title = "Stop farting (when typed phonetic combination is invalid, etc.)"; ObjectID = "ArK-Vk-OoT"; */
"ArK-Vk-OoT.title" = "不要放屁 // 例:当输入的音韵有误时,等。";
/* Class = "NSButtonCell"; title = "Auto-convert traditional Chinese glyphs to KangXi characters"; ObjectID = "BSK-bH-Gct"; */
"BSK-bH-Gct.title" = "自动将繁体中文字转换为康熙字";

View File

@ -101,6 +101,9 @@
/* Class = "NSTextFieldCell"; title = "UI language setting:"; ObjectID = "9DS-Rc-TXq"; */
"9DS-Rc-TXq.title" = "介面語言設定:";
/* Class = "NSButtonCell"; title = "Stop farting (when typed phonetic combination is invalid, etc.)"; ObjectID = "ArK-Vk-OoT"; */
"ArK-Vk-OoT.title" = "不要放屁 // 例:當輸入的音韻有誤時,等。";
/* Class = "NSButtonCell"; title = "Auto-convert traditional Chinese glyphs to KangXi characters"; ObjectID = "BSK-bH-Gct"; */
"BSK-bH-Gct.title" = "自動將繁體中文字轉換為康熙字";

View File

@ -23,6 +23,9 @@
5BC3EE1C278FC48C00F5E44C /* VTCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE19278FC48C00F5E44C /* VTCandidateController.swift */; };
5BC3EE1D278FC48C00F5E44C /* HorizontalCandidateController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC3EE1A278FC48C00F5E44C /* HorizontalCandidateController.swift */; };
5BC3FB83278492DE0022E99A /* data-chs.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BC3FB82278492DE0022E99A /* data-chs.txt */; };
5BD0D19427940E9D0008F48E /* Fart.aif in Resources */ = {isa = PBXBuildFile; fileRef = 5BD0D19327940E9D0008F48E /* Fart.aif */; };
5BD0D19A27943D390008F48E /* clsSFX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD0D19927943D390008F48E /* clsSFX.swift */; };
5BD0D19F279454F60008F48E /* Beep.aif in Resources */ = {isa = PBXBuildFile; fileRef = 5BD0D19E279454F60008F48E /* Beep.aif */; };
5BD0D1A4279463510008F48E /* clsOOBEDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD0D1A3279463510008F48E /* clsOOBEDefaults.swift */; };
5BDF2CFE2791BE4400838ADB /* InputSourceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDF2CFD2791BE4400838ADB /* InputSourceHelper.swift */; };
5BDF2CFF2791BECC00838ADB /* InputSourceHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDF2CFD2791BE4400838ADB /* InputSourceHelper.swift */; };
@ -114,6 +117,9 @@
5BC3EE19278FC48C00F5E44C /* VTCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VTCandidateController.swift; sourceTree = "<group>"; };
5BC3EE1A278FC48C00F5E44C /* HorizontalCandidateController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HorizontalCandidateController.swift; sourceTree = "<group>"; };
5BC3FB82278492DE0022E99A /* data-chs.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "data-chs.txt"; sourceTree = "<group>"; };
5BD0D19327940E9D0008F48E /* Fart.aif */ = {isa = PBXFileReference; lastKnownFileType = file; path = Fart.aif; sourceTree = "<group>"; };
5BD0D19927943D390008F48E /* clsSFX.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = clsSFX.swift; sourceTree = "<group>"; };
5BD0D19E279454F60008F48E /* Beep.aif */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beep.aif; sourceTree = "<group>"; };
5BD0D1A3279463510008F48E /* clsOOBEDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = clsOOBEDefaults.swift; sourceTree = "<group>"; };
5BDF2CFD2791BE4400838ADB /* InputSourceHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputSourceHelper.swift; sourceTree = "<group>"; };
5BDF2D002791C03B00838ADB /* PreferencesWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesWindowController.swift; sourceTree = "<group>"; };
@ -287,6 +293,14 @@
path = Keyboard;
sourceTree = "<group>";
};
5BD0D19827943D270008F48E /* SFX */ = {
isa = PBXGroup;
children = (
5BD0D19927943D390008F48E /* clsSFX.swift */,
);
path = SFX;
sourceTree = "<group>";
};
5BE798A12792E50F00337FF9 /* UI */ = {
isa = PBXGroup;
children = (
@ -396,6 +410,7 @@
6A0D4F1215FC0EB100ABF4B3 /* Engine */ = {
isa = PBXGroup;
children = (
5BD0D19827943D270008F48E /* SFX */,
5BC2D2892793B8DB002C0BEC /* Keyboard */,
5BC2D2832793B434002C0BEC /* vChewing */,
5BA8DAFE27928120009C9FFF /* LanguageModel */,
@ -475,6 +490,8 @@
6A0D4F4715FC0EB900ABF4B3 /* Resources */ = {
isa = PBXGroup;
children = (
5BD0D19E279454F60008F48E /* Beep.aif */,
5BD0D19327940E9D0008F48E /* Fart.aif */,
5BF4A70227844DC5007DC6E7 /* frmAboutWindow.xib */,
6AFF97F0253B299E007F1C49 /* NonModalAlertWindowController.xib */,
6A0D4EEE15FC0DA600ABF4B3 /* Images */,
@ -652,11 +669,13 @@
5B000FC3278495AD004F02AC /* SimpBopomofo.tiff in Resources */,
6A0D4F5815FC0EF900ABF4B3 /* Localizable.strings in Resources */,
6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */,
6A38BC1515FC117A00A8A51F /* data.txt in Resources */,
5BD0D19427940E9D0008F48E /* Fart.aif in Resources */,
6A38BC1515FC117A00A8A51F /* data-cht.txt in Resources */,
6AFF97F2253B299E007F1C49 /* NonModalAlertWindowController.xib in Resources */,
5B58E87F278413E7003EA2AD /* MITLicense.txt in Resources */,
6A187E2616004C5900466B2E /* MainMenu.xib in Resources */,
5BF4A70027844DC5007DC6E7 /* frmAboutWindow.xib in Resources */,
5BD0D19F279454F60008F48E /* Beep.aif in Resources */,
5BC3FB83278492DE0022E99A /* data-chs.txt in Resources */,
5B000FC4278495AD004F02AC /* SimpBopomofo@2x.tiff in Resources */,
5BC2D2872793B434002C0BEC /* CMakeLists.txt in Resources */,
@ -706,6 +725,7 @@
files = (
5BDF2CFE2791BE4400838ADB /* InputSourceHelper.swift in Sources */,
5BC2D28B2793B8FB002C0BEC /* EmacsKeyHelper.swift in Sources */,
5BD0D19A27943D390008F48E /* clsSFX.swift in Sources */,
5BE798A72793280C00337FF9 /* NotifierController.swift in Sources */,
5B5F4F93279294A300922DC2 /* LanguageModelManager.mm in Sources */,
6A0D4ED215FC0D6400ABF4B3 /* InputMethodController.mm in Sources */,