|
@@ -0,0 +1,541 @@
|
|
|
+//
|
|
|
+// KMTTSWindowController.swift
|
|
|
+// PDF Master
|
|
|
+//
|
|
|
+// Created by liujiajie on 2023/12/12.
|
|
|
+//
|
|
|
+
|
|
|
+import Cocoa
|
|
|
+
|
|
|
+typealias TTSCloseWindowCallback = (_ isCloseWindow: Bool) -> Void
|
|
|
+
|
|
|
+let minSpeed: Float = 0.6
|
|
|
+let maxSpeed: Float = 5.0
|
|
|
+let standardSpeed: Float = 175.0
|
|
|
+
|
|
|
+class KMTTSWindowController: NSWindowController, KMTTSManagerDelegate, NSWindowDelegate, NSTextFieldDelegate{
|
|
|
+ var pdfView: CPDFView!
|
|
|
+ var closeWindowCallback: TTSCloseWindowCallback?
|
|
|
+ @IBOutlet var sontinuouButton: NSButton!
|
|
|
+ @IBOutlet var speedLabel: NSTextField!
|
|
|
+ @IBOutlet var languageLabel: NSTextField!
|
|
|
+
|
|
|
+ @IBOutlet var languageComboBox: NSPopUpButton!
|
|
|
+ @IBOutlet var speedTextField: NSTextField!
|
|
|
+ @IBOutlet var speedSlider: NSSlider!
|
|
|
+
|
|
|
+ @IBOutlet var speedStepper: NSStepper!
|
|
|
+ @IBOutlet var nextButton: KMToolbarItem!
|
|
|
+ @IBOutlet var forwardButton: KMToolbarItem!
|
|
|
+
|
|
|
+ @IBOutlet var playButton: KMToolbarItem!
|
|
|
+
|
|
|
+ @IBOutlet var speedBox: NSBox!
|
|
|
+
|
|
|
+
|
|
|
+ @IBOutlet var sppendCountLabel: NSTextField!
|
|
|
+
|
|
|
+
|
|
|
+ var pdfSelection: CPDFSelection?
|
|
|
+
|
|
|
+ var currentPageIndex: Int = 0
|
|
|
+
|
|
|
+ var isChangePage = false
|
|
|
+
|
|
|
+ var voiceArrays = NSMutableArray()
|
|
|
+
|
|
|
+ static let share = KMTTSWindowController()
|
|
|
+
|
|
|
+ convenience init() {
|
|
|
+ self.init(windowNibName: "KMTTSWindowController")
|
|
|
+ }
|
|
|
+
|
|
|
+ override func windowDidLoad() {
|
|
|
+ super.windowDidLoad()
|
|
|
+ self.speedStepper.minValue = Double(minSpeed)
|
|
|
+ self.speedStepper.maxValue = Double(maxSpeed);
|
|
|
+ self.speedSlider.minValue = Double(minSpeed);
|
|
|
+ self.speedSlider.maxValue = Double(maxSpeed);
|
|
|
+
|
|
|
+ self.nextButton.toolTip = KMLocalizedString("Next Page", nil)
|
|
|
+// self.nextButton.isShowCustomToolTip = true
|
|
|
+ self.forwardButton.toolTip = KMLocalizedString("Previous Page", nil)
|
|
|
+// self.forwardButton.isShowCustomToolTip = true
|
|
|
+ self.speedSlider.isEnabled = true
|
|
|
+ self.speedStepper.isEnabled = true
|
|
|
+ self.playButton.toolTip = KMLocalizedString("Play", nil)
|
|
|
+// self.playButton.isShowCustomToolTip = true
|
|
|
+ self.sppendCountLabel.stringValue = KMLocalizedString("SpeedX", nil)
|
|
|
+ let str = String(format: "%.1f", KMTTSManager.defalutManager.rate/Float(standardSpeed))
|
|
|
+ self.speedStepper.stringValue = str
|
|
|
+ self.speedTextField.stringValue = str
|
|
|
+ self.speedSlider.stringValue = str//[NSString stringWithFormat:@"%.1f",([KMTTSManager defaultManager].rate/standardSpeed)];
|
|
|
+
|
|
|
+ self.sontinuouButton.title = KMLocalizedString("Continuous Reading", nil);
|
|
|
+ self.speedLabel.stringValue = KMLocalizedString("Speed", nil) + ":"//[NSString stringWithFormat:@"%@:",KMLocalizedString("Speed", nil)];
|
|
|
+ self.languageLabel.stringValue = KMLocalizedString("Language", nil) + ":" //[NSString stringWithFormat:@"%@:",KMLocalizedString(@"Language", nil)];
|
|
|
+
|
|
|
+ let array = KMTTSManager.defalutManager.availableVoices()
|
|
|
+ let currentVoicName = KMTTSManager.defalutManager.voice()
|
|
|
+ var currentIndex = 0
|
|
|
+ let menu = NSMenu()
|
|
|
+
|
|
|
+ for voiceType: NSSpeechSynthesizer.VoiceName in array {
|
|
|
+ let voiceDic = NSMutableDictionary()
|
|
|
+ // let dic = KMTTSManager.defalutManager.attributesForVoice(voiceType)
|
|
|
+ let voiceLocaleIdentifier = ( NSSpeechSynthesizer.attributes( forVoice: voiceType )[ NSSpeechSynthesizer.VoiceAttributeKey.localeIdentifier ] as! String )
|
|
|
+
|
|
|
+ let name = self.switchLanguage(withCode: voiceLocaleIdentifier)
|
|
|
+ voiceDic["voiceType"] = voiceType
|
|
|
+ voiceDic["voiceName"] = name
|
|
|
+ voiceArrays.add(voiceDic)
|
|
|
+ }
|
|
|
+ voiceArrays = self.sortArray(voiceArrays)
|
|
|
+ for i in 0..<voiceArrays.count {
|
|
|
+ let voiceDic = voiceArrays[i] as! NSDictionary
|
|
|
+ let voiceType = voiceDic.object(forKey: "voiceType") as! NSSpeechSynthesizer.VoiceName
|
|
|
+ if currentVoicName == voiceType {
|
|
|
+ currentIndex = i
|
|
|
+ }
|
|
|
+
|
|
|
+ let dic = KMTTSManager.defalutManager.attributesForVoice(voiceType) as NSDictionary
|
|
|
+ let code = ( NSSpeechSynthesizer.attributes( forVoice: voiceType )[ NSSpeechSynthesizer.VoiceAttributeKey.localeIdentifier ] as! String )
|
|
|
+ var languageStaring: String? = nil
|
|
|
+ let voiceName = ( NSSpeechSynthesizer.attributes( forVoice: voiceType )[ NSSpeechSynthesizer.VoiceAttributeKey.name ] as! String )
|
|
|
+ let name = self.switchLanguage(withCode: code)
|
|
|
+ if voiceName.count > 0 {
|
|
|
+ languageStaring = "\(name)(\(voiceName))"
|
|
|
+ }
|
|
|
+
|
|
|
+ let font = NSFont.systemFont(ofSize: 12.0)
|
|
|
+ let namefont = NSFont.systemFont(ofSize: 10.0)
|
|
|
+
|
|
|
+ let textRowSpace = NSMutableAttributedString(string: languageStaring ?? "")
|
|
|
+ textRowSpace.addAttribute(.font, value: font, range: NSRange(location: 0, length: name.count))
|
|
|
+ textRowSpace.addAttribute(.font, value: namefont, range: NSRange(location: name.count, length: languageStaring!.count - name.count))
|
|
|
+ let item = NSMenuItem()
|
|
|
+ item.attributedTitle = textRowSpace
|
|
|
+ menu.addItem(item)
|
|
|
+ }
|
|
|
+ self.languageComboBox.menu = menu
|
|
|
+ self.languageComboBox.selectItem(at: currentIndex)
|
|
|
+ KMTTSManager.defalutManager.delegate = self
|
|
|
+ self.updateViewColor()
|
|
|
+ self.window?.standardWindowButton(.zoomButton)?.isHidden = true
|
|
|
+ if KMTTSManager.defalutManager.isContinue {
|
|
|
+ self.sontinuouButton.state = .on
|
|
|
+ } else {
|
|
|
+ self.sontinuouButton.state = .off
|
|
|
+ }
|
|
|
+ DistributedNotificationCenter.default().addObserver(self, selector: #selector(themeChanged(notification:)), name: NSNotification.Name("AppleInterfaceThemeChangedNotification"), object: nil)
|
|
|
+
|
|
|
+ NotificationCenter.default.addObserver(self, selector: #selector(handlePageChangedNotification), name: NSNotification.Name.CPDFViewPageChanged, object: self.pdfView)
|
|
|
+ }
|
|
|
+
|
|
|
+ func updateViewColor() {
|
|
|
+ var viewBackcolor = NSColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0)
|
|
|
+ var textColor = NSColor(red: 51.0/255.0, green: 51.0/255.0, blue: 51.0/255.0, alpha: 1.0)
|
|
|
+ var contentColor = NSColor(red: 102.0/255.0, green: 102.0/255.0, blue: 102.0/255.0, alpha: 1.0)
|
|
|
+ var fillColor = NSColor.white
|
|
|
+ if #available(macOS 10.14, *) {
|
|
|
+ let appearanceName = NSApp.effectiveAppearance.bestMatch(from: [.aqua, .darkAqua])
|
|
|
+ if appearanceName == .darkAqua {
|
|
|
+ viewBackcolor = NSColor(red: 69.0/255.0, green: 69.0/255.0, blue: 71.0/255.0, alpha: 1.0)
|
|
|
+ textColor = NSColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0)
|
|
|
+ contentColor = NSColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 0.6)
|
|
|
+ fillColor = NSColor(red: 101.0/255.0, green: 101.0/255.0, blue: 101.0/255.0, alpha: 1.0)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ self.window?.backgroundColor = viewBackcolor
|
|
|
+ self.window?.isMovableByWindowBackground = true
|
|
|
+ self.languageLabel.textColor = contentColor
|
|
|
+ self.speedLabel.textColor = contentColor
|
|
|
+ self.speedTextField.textColor = textColor
|
|
|
+ self.speedBox.fillColor = fillColor
|
|
|
+ self.sontinuouButton.setTitleColor(contentColor)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @objc func themeChanged(notification: NSNotification) {
|
|
|
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
|
|
+ self.updateViewColor()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @objc func handlePageChangedNotification(notification: NSNotification) {
|
|
|
+ guard let PDFView = notification.object as? CPDFView else { return }
|
|
|
+ if PDFView == self.pdfView {
|
|
|
+ if self.pdfView.canGoToNextPage() {
|
|
|
+ self.nextButton.isEnabled = true
|
|
|
+ } else{
|
|
|
+ self.nextButton.isEnabled = false
|
|
|
+ }
|
|
|
+ if self.pdfView.canGoToPreviousPage() {
|
|
|
+ self.forwardButton.isEnabled = true
|
|
|
+ } else {
|
|
|
+ self.forwardButton.isEnabled = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ func sortArray(_ array: NSArray) -> NSMutableArray {
|
|
|
+ let sortDesc = [NSSortDescriptor(key: "voiceName", ascending: true)]
|
|
|
+ let sortedArr = array.sortedArray(using: sortDesc) as NSArray
|
|
|
+ let tArray = NSMutableArray(array: sortedArr)
|
|
|
+ return tArray
|
|
|
+ }
|
|
|
+
|
|
|
+ func windowShouldClose(_ sender: NSWindow) -> Bool {
|
|
|
+ self.stopSpeaking()
|
|
|
+ if let callBlack = closeWindowCallback {
|
|
|
+ callBlack(true)
|
|
|
+ }
|
|
|
+ return true
|
|
|
+ }
|
|
|
+
|
|
|
+ override func showWindow(_ sender: Any?) {
|
|
|
+ super.showWindow(sender)
|
|
|
+ self.isChangePage = false
|
|
|
+ if self.pdfView.canGoToNextPage() {
|
|
|
+ self.nextButton.isEnabled = true
|
|
|
+ } else{
|
|
|
+ self.nextButton.isEnabled = false
|
|
|
+ }
|
|
|
+ if self.pdfView.canGoToPreviousPage() {
|
|
|
+ self.forwardButton.isEnabled = true
|
|
|
+ } else {
|
|
|
+ self.forwardButton.isEnabled = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func stopSpeaking() {
|
|
|
+ if KMTTSManager.defalutManager.isSpeaking() || KMTTSManager.defalutManager.isPaused {
|
|
|
+ self.isChangePage = true
|
|
|
+ KMTTSManager.defalutManager.stopSpeaking()
|
|
|
+ self.speedSlider.isEnabled = true
|
|
|
+ self.speedStepper.isEnabled = true
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSStop")
|
|
|
+ self.playButton.toolTip = NSLocalizedString("Play", comment: "")
|
|
|
+ self.pdfView.setHighlightedSelections([])
|
|
|
+ }
|
|
|
+ self.pdfSelection = nil
|
|
|
+ self.pdfView = nil
|
|
|
+ }
|
|
|
+
|
|
|
+ func quikeStartSpeakingPDFPage(_ page: CPDFPage) {
|
|
|
+ if KMTTSManager.defalutManager.isSpeaking() || KMTTSManager.defalutManager.isPaused {
|
|
|
+ KMTTSManager.defalutManager.stopSpeaking()
|
|
|
+ self.isChangePage = true
|
|
|
+ }
|
|
|
+ self.currentPageIndex = Int(self.pdfView.document?.index(for: page) ?? 0)
|
|
|
+ self.startSpeakingPDFPage(page)
|
|
|
+ }
|
|
|
+ func startSpeakingPDFPage(_ page: CPDFPage) {
|
|
|
+ let dex = self.languageComboBox.indexOfSelectedItem
|
|
|
+ if dex >= 0 && dex < self.voiceArrays.count {
|
|
|
+ let dic: NSMutableDictionary = self.voiceArrays[dex] as! NSMutableDictionary
|
|
|
+ if let voiceName = dic["voiceType"] {
|
|
|
+ KMTTSManager.defalutManager.setVoice(voice: voiceName as! NSSpeechSynthesizer.VoiceName)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ KMTTSManager.defalutManager.rate = self.speedSlider.floatValue * Float(standardSpeed)
|
|
|
+ let isSuccess = KMTTSManager.defalutManager.startSpeakingPDFPage(page)
|
|
|
+ if isSuccess {
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSPause")
|
|
|
+ self.playButton.toolTip = NSLocalizedString("Pause", comment: "")
|
|
|
+ self.speedSlider.isEnabled = false
|
|
|
+ self.speedStepper.isEnabled = false
|
|
|
+ } else {
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSStop")
|
|
|
+ self.playButton.toolTip = NSLocalizedString("Play", comment: "")
|
|
|
+ self.speedSlider.isEnabled = true
|
|
|
+ self.speedStepper.isEnabled = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ func startSpeakingPDFSelection(_ selection: CPDFSelection) {
|
|
|
+ if KMTTSManager.defalutManager.isSpeaking() || KMTTSManager.defalutManager.isPaused {
|
|
|
+ KMTTSManager.defalutManager.stopSpeaking()
|
|
|
+ self.isChangePage = true
|
|
|
+ }
|
|
|
+ self.pdfSelection = selection
|
|
|
+ self.pdfView?.setCurrentSelection(nil, animate: false)
|
|
|
+ let dex = self.languageComboBox.indexOfSelectedItem
|
|
|
+ if dex >= 0 && dex < self.voiceArrays.count {
|
|
|
+ let dic: NSMutableDictionary = self.voiceArrays[dex] as! NSMutableDictionary
|
|
|
+ if let voiceName = dic["voiceType"] as? NSSpeechSynthesizer.VoiceName {
|
|
|
+ KMTTSManager.defalutManager.setVoice(voice: voiceName)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ KMTTSManager.defalutManager.rate = self.speedSlider.floatValue * Float(standardSpeed)
|
|
|
+ let isSuccess = KMTTSManager.defalutManager.startSpeakingPDFSelection(selection)
|
|
|
+ if isSuccess {
|
|
|
+ self.speedSlider.isEnabled = false
|
|
|
+ self.speedStepper.isEnabled = false
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSPause")
|
|
|
+ self.playButton.toolTip = NSLocalizedString("Pause", comment: "")
|
|
|
+ } else {
|
|
|
+ self.speedSlider.isEnabled = true
|
|
|
+ self.speedStepper.isEnabled = true
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSStop")
|
|
|
+ self.playButton.toolTip = NSLocalizedString("Play", comment: "")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @IBAction func buttonItemClick_Next(_ sender: NSButton) {
|
|
|
+ if (KMTTSManager.defalutManager.isSpeaking()) {
|
|
|
+ var currentPageNum = self.currentPageIndex;
|
|
|
+ var page: CPDFPage?
|
|
|
+ if (currentPageNum + 1 < self.pdfView.document.pageCount) {
|
|
|
+ page = self.pdfView.document.page(at: UInt(currentPageNum+1))
|
|
|
+ self.currentPageIndex = currentPageNum + 1;
|
|
|
+
|
|
|
+ } else {
|
|
|
+ page = self.pdfView.document.page(at: self.pdfView.document.pageCount - 1)
|
|
|
+ self.currentPageIndex = Int(self.pdfView.document.pageCount - 1)
|
|
|
+ }
|
|
|
+ self.pdfView.go(to: page)
|
|
|
+ self.isChangePage = true
|
|
|
+ self.startSpeakingPDFPage(page!)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @IBAction func buttonItemClick_Forward(_ sender: NSButton) {
|
|
|
+ if (KMTTSManager.defalutManager.isSpeaking()) {
|
|
|
+ var currentPageNum = self.currentPageIndex;
|
|
|
+ var page: CPDFPage?
|
|
|
+ if (currentPageNum - 1 < 0) {
|
|
|
+ page = self.pdfView.document.page(at: 0)
|
|
|
+ self.currentPageIndex = 0;
|
|
|
+
|
|
|
+ } else {
|
|
|
+ page = self.pdfView.document.page(at: UInt(currentPageNum - 1))
|
|
|
+ self.currentPageIndex = currentPageNum - 1
|
|
|
+ }
|
|
|
+ self.pdfView.go(to: page)
|
|
|
+ self.isChangePage = true
|
|
|
+ self.startSpeakingPDFPage(page!)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @IBAction func buttonItemClick_Play(_ sender: NSButton) {
|
|
|
+ if (KMTTSManager.defalutManager.isPaused) {
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSPause")
|
|
|
+ self.playButton.toolTip = KMLocalizedString("Pause", nil)
|
|
|
+ self.speedSlider.isEnabled = false
|
|
|
+ self.speedStepper.isEnabled = false
|
|
|
+ KMTTSManager.defalutManager.continueSpeaking()
|
|
|
+ } else if (KMTTSManager.defalutManager.isSpeaking()) {
|
|
|
+ self.isChangePage = true
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSStop")
|
|
|
+ self.playButton.toolTip = KMLocalizedString("Play", nil)
|
|
|
+
|
|
|
+ self.speedSlider.isEnabled = true
|
|
|
+ self.speedStepper.isEnabled = true
|
|
|
+ self.pdfView.setHighlightedSelection(nil, animated: false)
|
|
|
+ KMTTSManager.defalutManager.pauseSpeaking()
|
|
|
+ } else {
|
|
|
+ if ((self.pdfSelection) != nil) {
|
|
|
+ self.startSpeakingPDFSelection(self.pdfSelection!)
|
|
|
+ } else {
|
|
|
+ let page = self.pdfView.currentPage()
|
|
|
+ self.currentPageIndex = self.pdfView.currentPageIndex
|
|
|
+ self.startSpeakingPDFPage(page!)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ @IBAction func buttonItemClick_Continue(_ sender: NSButton) {
|
|
|
+ KMTTSManager.defalutManager.isContinue = !(KMTTSManager.defalutManager.isContinue)
|
|
|
+ }
|
|
|
+ @IBAction func stepperItemClick_Speed(_ sender: NSButton) {
|
|
|
+ var rate = self.speedStepper.floatValue
|
|
|
+ let str = String(format: "%.1f", rate)
|
|
|
+ self.speedStepper.stringValue = str
|
|
|
+ self.speedTextField.stringValue = str
|
|
|
+ self.speedSlider.stringValue = str
|
|
|
+ rate = Float(standardSpeed) * rate
|
|
|
+ KMTTSManager.defalutManager.rate = rate
|
|
|
+ }
|
|
|
+ @IBAction func sliderItemClick_Speed(_ sender: NSButton) {
|
|
|
+ var rate: CGFloat = CGFloat(self.speedSlider.floatValue)
|
|
|
+ self.speedStepper.stringValue = "\(rate)"
|
|
|
+ self.speedTextField.stringValue = "\(rate)"
|
|
|
+ self.speedSlider.stringValue = "\(rate)"
|
|
|
+ rate = CGFloat(standardSpeed) * rate
|
|
|
+ KMTTSManager.defalutManager.rate = Float(rate)
|
|
|
+ }
|
|
|
+ @IBAction func buttonItemClick_Language(_ sender: NSButton) {
|
|
|
+ if KMTTSManager.defalutManager.isSpeaking() {
|
|
|
+ self.isChangePage = true
|
|
|
+ if let pdfSelection = self.pdfSelection {
|
|
|
+ self.startSpeakingPDFSelection(pdfSelection)
|
|
|
+ } else {
|
|
|
+ let currentPageInd = self.currentPageIndex
|
|
|
+ if currentPageInd < (self.pdfView.document.pageCount - 1) {
|
|
|
+ let page = self.pdfView.document.page(at: UInt(currentPageInd))
|
|
|
+ self.startSpeakingPDFPage(page!)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ override func mouseDown(with event: NSEvent) {
|
|
|
+ super.mouseDown(with: event)
|
|
|
+ self.window?.makeFirstResponder(self)
|
|
|
+ }
|
|
|
+ //MARK: KMTTSManagerDelegate
|
|
|
+ func ttsMananger(_ tts: KMTTSManager, willSpeak selection: CPDFSelection) {
|
|
|
+// if (selection != nil) {
|
|
|
+ self.pdfView.setHighlightedSelection(selection, animated: false)
|
|
|
+// }
|
|
|
+ }
|
|
|
+ func ttsManangerDidFinishSpeech(_ tts: KMTTSManager) -> Bool {
|
|
|
+ var isFinish = true
|
|
|
+ if self.pdfSelection != nil {
|
|
|
+ self.pdfSelection = nil
|
|
|
+ self.pdfView.setHighlightedSelections(nil)
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSStop")
|
|
|
+ self.speedSlider.isEnabled = true
|
|
|
+ self.speedStepper.isEnabled = true
|
|
|
+ self.playButton.toolTip = KMLocalizedString("Play", nil)
|
|
|
+ } else {
|
|
|
+ if KMTTSManager.defalutManager.isContinue {
|
|
|
+ if !isChangePage {
|
|
|
+ if let pdfSelection = self.pdfSelection {
|
|
|
+ self.pdfView.setHighlightedSelections(nil)
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSStop")
|
|
|
+ self.speedSlider.isEnabled = true
|
|
|
+ self.speedStepper.isEnabled = true
|
|
|
+ self.playButton.toolTip = KMLocalizedString("Play", nil)
|
|
|
+ } else {
|
|
|
+ let currentPageIndex = self.currentPageIndex
|
|
|
+ if currentPageIndex + 1 < self.pdfView.document.pageCount {
|
|
|
+ let page = self.pdfView.document.page(at: UInt(currentPageIndex+1))
|
|
|
+ self.currentPageIndex = currentPageIndex+1
|
|
|
+ self.pdfView.go(to: page)
|
|
|
+ self.startSpeakingPDFPage(page!)
|
|
|
+ isFinish = false
|
|
|
+ } else {
|
|
|
+ self.pdfView.setHighlightedSelections(nil)
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSStop")
|
|
|
+ self.speedSlider.isEnabled = true
|
|
|
+ self.speedStepper.isEnabled = true
|
|
|
+ self.playButton.toolTip = KMLocalizedString("Play", nil)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if !isChangePage {
|
|
|
+ self.speedSlider.isEnabled = true
|
|
|
+ self.speedStepper.isEnabled = true
|
|
|
+ self.pdfView.setHighlightedSelections(nil)
|
|
|
+ self.playButton.image = NSImage(named: "KMImageNameTTSStop")
|
|
|
+ self.playButton.toolTip = KMLocalizedString("Play", nil)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if isChangePage {
|
|
|
+ isChangePage = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return isFinish
|
|
|
+ }
|
|
|
+ func ttsManangerdidErrorSpeech(_ tts: KMTTSManager, message: String) {
|
|
|
+
|
|
|
+ }
|
|
|
+ //MARK: NSTextFieldDelegate
|
|
|
+ func controlTextDidEndEditing(_ obj: Notification) {
|
|
|
+ if let textField = obj.object as? NSTextField {
|
|
|
+ if textField == self.speedTextField {
|
|
|
+ var rate: Float = Float(textField.stringValue) ?? 0
|
|
|
+ if maxSpeed - rate < 0 {
|
|
|
+ rate = maxSpeed
|
|
|
+ } else if rate - minSpeed < 0 {
|
|
|
+ rate = minSpeed
|
|
|
+ }
|
|
|
+ self.speedStepper.stringValue = String(format: "%.1f", rate)
|
|
|
+ self.speedTextField.stringValue = String(format: "%.1f", rate)
|
|
|
+ self.speedSlider.stringValue = String(format: "%.1f", rate)
|
|
|
+ rate = standardSpeed * rate
|
|
|
+ KMTTSManager.defalutManager.rate = rate
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func switchLanguage(withCode code: String) -> String {
|
|
|
+ var language = code
|
|
|
+ if code == "ar_SA" {
|
|
|
+ language = "Arabic (Saudi Arabia)"
|
|
|
+ } else if code == "cs_CZ" {
|
|
|
+ language = "Czech (Czech republic)"
|
|
|
+ } else if code == "da_DK" {
|
|
|
+ language = "Danish (Denmark)"
|
|
|
+ } else if code == "de_DE" {
|
|
|
+ language = "German (Germany)"
|
|
|
+ } else if code == "el_GR" {
|
|
|
+ language = "Greek (Greece)"
|
|
|
+ } else if code == "en_AU" {
|
|
|
+ language = "English (Australia)"
|
|
|
+ } else if code == "en_GB" {
|
|
|
+ language = "English (UK)"
|
|
|
+ } else if code == "en_IE" {
|
|
|
+ language = "English (Ireland)"
|
|
|
+ } else if code == "en_US" {
|
|
|
+ language = "English"
|
|
|
+ } else if code == "en_ZA" {
|
|
|
+ language = "English (South Africa)"
|
|
|
+ } else if code == "es_ES" {
|
|
|
+ language = "Spanish (Spain)"
|
|
|
+ } else if code == "es_MX" {
|
|
|
+ language = "Spanish (Mexico)"
|
|
|
+ } else if code == "fi_FI" {
|
|
|
+ language = "Finnish (Finland)"
|
|
|
+ } else if code == "fr_CA" {
|
|
|
+ language = "French (Canada)"
|
|
|
+ } else if code == "fr_FR" {
|
|
|
+ language = "French (France)"
|
|
|
+ } else if code == "he_IL" {
|
|
|
+ language = "Hebrew"
|
|
|
+ } else if code == "hi_IN" {
|
|
|
+ language = "Hindi (India)"
|
|
|
+ } else if code == "hu_HU" {
|
|
|
+ language = "Hungarian (Hungary)"
|
|
|
+ } else if code == "id_ID" {
|
|
|
+ language = "Indonesian (Indonesia)"
|
|
|
+ } else if code == "it_IT" {
|
|
|
+ language = "Italian (Italy)"
|
|
|
+ } else if code == "ja_JP" {
|
|
|
+ language = "日本語"
|
|
|
+ } else if code == "ko_KR" {
|
|
|
+ language = "Korean (South Korea)"
|
|
|
+ } else if code == "nl_BE" {
|
|
|
+ language = "Dutch (Belgium)"
|
|
|
+ } else if code == "nl_NL" {
|
|
|
+ language = "Dutch (Holland)"
|
|
|
+ } else if code == "nb_NO" {
|
|
|
+ language = "Norwegian (Norway)"
|
|
|
+ } else if code == "pl_PL" {
|
|
|
+ language = "Polish (Poland)"
|
|
|
+ } else if code == "pt_BR" {
|
|
|
+ language = "Portuguese (Brazil)"
|
|
|
+ } else if code == "pt_PT" {
|
|
|
+ language = "Portuguese (Portugal)"
|
|
|
+ } else if code == "ro_RO" {
|
|
|
+ language = "Romanian (Romania)"
|
|
|
+ } else if code == "ru_RU" {
|
|
|
+ language = "Russian (Russia)"
|
|
|
+ } else if code == "sk_SK" {
|
|
|
+ language = "Slovakia (Slovakia)"
|
|
|
+ } else if code == "sv_SE" {
|
|
|
+ language = "Swe (Sweden)"
|
|
|
+ } else if code == "th_TH" {
|
|
|
+ language = "Thai (Thailand)"
|
|
|
+ } else if code == "tr_TR" {
|
|
|
+ language = "Turkish (Turkey)"
|
|
|
+ } else if code == "zh_CN" {
|
|
|
+ language = "简体中文"
|
|
|
+ } else if code == "zh_HK" {
|
|
|
+ language = "繁體中文 (香港)"
|
|
|
+ } else if code == "zh_TW" {
|
|
|
+ language = "繁體中文 (台灣)"
|
|
|
+ } else if code == "en_IN" {
|
|
|
+ language = "English"
|
|
|
+ }
|
|
|
+ return language
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|