KMTTSManager.swift 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. //
  2. // KMTTSManager.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by liujiajie on 2023/12/12.
  6. //
  7. @objc(KMTTSManagerDelegate)
  8. protocol KMTTSManagerDelegate: AnyObject {
  9. @objc optional func ttsMananger(_ tts: KMTTSManager, willSpeak selection: CPDFSelection)
  10. @objc optional func ttsManangerDidFinishSpeech(_ tts: KMTTSManager) -> Bool
  11. @objc optional func ttsManangerdidErrorSpeech(_ tts: KMTTSManager, message: String)
  12. }
  13. let KMTTS_SETTING_SPEECHSPEED_KEY = "TTS_Setting_SpeechSpeed_Key"
  14. let KMTTS_SETTING_ISCONTINUE_KEY = "TTS_Setting_IsContinue_Key"
  15. let KMTTS_SETTING_LANGUAGE_KEY = "TTS_Setting_Language_Key"
  16. import Foundation
  17. class KMTTSManager: NSObject, NSSpeechSynthesizerDelegate{
  18. var delegate: KMTTSManagerDelegate?
  19. var rate: Float {
  20. get{
  21. return self.speechSynthesizer.rate
  22. }
  23. set{
  24. self.speechSynthesizer.rate = newValue
  25. UserDefaults.standard.setValue(newValue, forKey: KMTTS_SETTING_SPEECHSPEED_KEY)
  26. UserDefaults.standard.synchronize()
  27. }
  28. }
  29. var isContinue = false {
  30. willSet {
  31. }
  32. didSet {
  33. UserDefaults.standard.setValue(isContinue, forKey: KMTTS_SETTING_ISCONTINUE_KEY)
  34. UserDefaults.standard.synchronize()
  35. }
  36. }
  37. func isSpeaking() -> Bool {
  38. return self.speechSynthesizer.isSpeaking
  39. }
  40. var isPaused = false
  41. var speechSynthesizer: NSSpeechSynthesizer!
  42. var speechPDFPage: CPDFPage?
  43. var speechPDFSelection: CPDFSelection?
  44. static let defalutManager = KMTTSManager()
  45. override init() {
  46. super.init()
  47. let array = NSSpeechSynthesizer.availableVoices
  48. var voice: NSSpeechSynthesizer.VoiceName = array.first ?? NSSpeechSynthesizer.VoiceName(rawValue: "")
  49. if (UserDefaults.standard.object(forKey: KMTTS_SETTING_LANGUAGE_KEY) != nil){
  50. voice = UserDefaults.standard.object(forKey: KMTTS_SETTING_LANGUAGE_KEY) as! NSSpeechSynthesizer.VoiceName
  51. }
  52. self.speechSynthesizer = NSSpeechSynthesizer(voice: voice)
  53. self.speechSynthesizer.delegate = self
  54. self.speechSynthesizer.usesFeedbackWindow = true
  55. var rate: Float = 175
  56. if let savedRate = UserDefaults.standard.object(forKey: KMTTS_SETTING_SPEECHSPEED_KEY) as? Float {
  57. rate = savedRate
  58. }
  59. self.speechSynthesizer.rate = rate
  60. var isContinue = false
  61. if let savedContinue = UserDefaults.standard.object(forKey: KMTTS_SETTING_ISCONTINUE_KEY) as? Bool {
  62. isContinue = savedContinue
  63. }
  64. self.isContinue = isContinue
  65. }
  66. func voice() -> NSSpeechSynthesizer.VoiceName {
  67. return self.speechSynthesizer.voice() ?? NSSpeechSynthesizer.VoiceName(rawValue: "")
  68. }
  69. func setVoice(voice: NSSpeechSynthesizer.VoiceName) {
  70. self.speechSynthesizer.setVoice(voice)
  71. UserDefaults.standard.setValue(voice, forKey: KMTTS_SETTING_LANGUAGE_KEY)
  72. UserDefaults.standard.synchronize()
  73. }
  74. //MARK: Public
  75. func startSpeakingPDFPage(_ page: CPDFPage) -> Bool {
  76. guard let string = page.string else { return false }
  77. guard string.count > 0 else { return false }
  78. isPaused = false
  79. if speechSynthesizer.isSpeaking {
  80. speechSynthesizer.stopSpeaking(at: .immediateBoundary)
  81. }
  82. speechPDFPage = page
  83. speechPDFSelection = nil
  84. return speechSynthesizer.startSpeaking(string)
  85. }
  86. func startSpeakingPDFSelection(_ selection: CPDFSelection) -> Bool {
  87. guard let string = selection.string() else { return false }
  88. guard string.count > 0 else { return false }
  89. isPaused = false
  90. if speechSynthesizer.isSpeaking {
  91. speechSynthesizer.stopSpeaking(at: .immediateBoundary)
  92. }
  93. speechPDFPage = nil
  94. speechPDFSelection = selection
  95. return speechSynthesizer.startSpeaking(string)
  96. }
  97. func stopSpeaking() {
  98. if speechSynthesizer.isSpeaking || isPaused {
  99. isPaused = false
  100. speechSynthesizer.stopSpeaking(at: .immediateBoundary)
  101. }
  102. }
  103. func pauseSpeaking() {
  104. if speechSynthesizer.isSpeaking {
  105. isPaused = true
  106. speechSynthesizer.pauseSpeaking(at: .immediateBoundary)
  107. }
  108. }
  109. func continueSpeaking() {
  110. isPaused = false
  111. speechSynthesizer.continueSpeaking()
  112. }
  113. func availableVoices() -> [NSSpeechSynthesizer.VoiceName] {
  114. return NSSpeechSynthesizer.availableVoices
  115. }
  116. func attributesForVoice(_ voice: NSSpeechSynthesizer.VoiceName) -> [NSSpeechSynthesizer.VoiceAttributeKey : Any] {
  117. return NSSpeechSynthesizer.attributes(forVoice: voice)
  118. }
  119. func speechSynthesizer(_ sender: NSSpeechSynthesizer, didFinishSpeaking finishedSpeaking: Bool) {
  120. isPaused = false
  121. let _ = delegate?.ttsManangerDidFinishSpeech?(self)
  122. }
  123. func speechSynthesizer(_ sender: NSSpeechSynthesizer, willSpeakWord characterRange: NSRange, of string: String) {
  124. var selection: CPDFSelection?
  125. if let page = speechPDFPage {
  126. if characterRange.length > 0 {
  127. selection = page.selection(for: characterRange)
  128. }
  129. } else if let pdfSelection = speechPDFSelection {
  130. selection = pdfSelection
  131. }
  132. if let data = selection {
  133. delegate?.ttsMananger?(self, willSpeak: data)
  134. }
  135. }
  136. func speechSynthesizer(_ sender: NSSpeechSynthesizer, didEncounterErrorAt characterIndex: Int, of string: String, message: String) {
  137. delegate?.ttsManangerdidErrorSpeech?(self, message: message)
  138. }
  139. func speechSynthesizer(_ sender: NSSpeechSynthesizer, didEncounterSyncMessage message: String) {
  140. delegate?.ttsManangerdidErrorSpeech?(self, message: message)
  141. }
  142. }