Skip to content

Commit

Permalink
Let speak instructions without route progress.
Browse files Browse the repository at this point in the history
  • Loading branch information
StephanPartzsch committed Mar 18, 2024
1 parent 039bedf commit e0339ef
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Examples/Swift/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ extension ViewController: VoiceControllerDelegate {
print(interruptedInstruction.text, interruptingInstruction.text)
}

func voiceController(_ voiceController: RouteVoiceController, willSpeak instruction: SpokenInstruction, routeProgress: RouteProgress) -> SpokenInstruction? {
func voiceController(_ voiceController: RouteVoiceController, willSpeak instruction: SpokenInstruction, routeProgress: RouteProgress?) -> SpokenInstruction? {
return SpokenInstruction(distanceAlongStep: instruction.distanceAlongStep, text: "New Instruction!", ssmlText: "<speak>New Instruction!</speak>")
}

Expand Down
45 changes: 19 additions & 26 deletions MapboxNavigation/RouteVoiceController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,9 @@ open class RouteVoiceController: NSObject, AVSpeechSynthesizerDelegate {

- parameter instruction: The instruction to read aloud.
- parameter locale: The `Locale` used to create the voice read aloud the given instruction. If `nil` the `Locale.preferredLocalLanguageCountryCode` is used for creating the voice.
- parameter ignoreProgress: A `Bool` that indicates if the routeProgress is added to the instruction.
*/
open func speak(_ instruction: SpokenInstruction, with locale: Locale?) {
guard let routeProgress else {
assertionFailure("routeProgress should not be nil.")
return
}

open func speak(_ instruction: SpokenInstruction, with locale: Locale?, ignoreProgress: Bool = false) {
if speechSynth.isSpeaking, let lastSpokenInstruction = lastSpokenInstruction {
voiceControllerDelegate?.voiceController?(self, didInterrupt: lastSpokenInstruction, with: instruction)
}
Expand All @@ -209,29 +205,26 @@ open class RouteVoiceController: NSObject, AVSpeechSynthesizerDelegate {
voiceControllerDelegate?.voiceController?(self, spokenInstructionsDidFailWith: error)
}

var utterance: AVSpeechUtterance?
let modifiedInstruction = voiceControllerDelegate?.voiceController?(self, willSpeak: instruction, routeProgress: routeProgress) ?? instruction

let utterance: AVSpeechUtterance

if locale?.identifier == "en-US" {
// Alex can’t handle attributed text.
utterance = AVSpeechUtterance(string: instruction.text)
utterance!.voice = AVSpeechSynthesisVoice(identifier: AVSpeechSynthesisVoiceIdentifierAlex)
}

let modifiedInstruction = voiceControllerDelegate?.voiceController?(self, willSpeak: instruction, routeProgress: routeProgress) ?? instruction

if #available(iOS 10.0, *), utterance?.voice == nil {
utterance = AVSpeechUtterance(attributedString: modifiedInstruction.attributedText(for: routeProgress.currentLegProgress))
} else {
utterance = AVSpeechUtterance(string: modifiedInstruction.text)
utterance.voice = AVSpeechSynthesisVoice(identifier: AVSpeechSynthesisVoiceIdentifierAlex)
} else {
if #available(iOS 10.0, *), !ignoreProgress, let routeProgress {
utterance = AVSpeechUtterance(attributedString: modifiedInstruction.attributedText(for: routeProgress.currentLegProgress))
} else {
utterance = AVSpeechUtterance(string: modifiedInstruction.text)
}

// Only localized languages will have a proper fallback voice
utterance.voice = AVSpeechSynthesisVoice(language: locale?.identifier ?? Locale.preferredLocalLanguageCountryCode)
}

// Only localized languages will have a proper fallback voice
if utterance?.voice == nil {
utterance?.voice = AVSpeechSynthesisVoice(language: locale?.identifier ?? Locale.preferredLocalLanguageCountryCode)
}

if let utterance = utterance {
speechSynth.speak(utterance)
}
speechSynth.speak(utterance)
}
}

Expand Down Expand Up @@ -264,8 +257,8 @@ public protocol VoiceControllerDelegate {

- parameter voiceController: The voice controller that will speak an instruction.
- parameter instruction: The spoken instruction that will be said.
- parameter routeProgress: The `RouteProgress` just before when the instruction is scheduled to be spoken.
- parameter routeProgress: The `RouteProgress` just before when the instruction is scheduled to be spoken. Could be `nil` if no progress is available or if oit should be ignored.
**/
@objc(voiceController:willSpeakSpokenInstruction:routeProgress:)
optional func voiceController(_ voiceController: RouteVoiceController, willSpeak instruction: SpokenInstruction, routeProgress: RouteProgress) -> SpokenInstruction?
optional func voiceController(_ voiceController: RouteVoiceController, willSpeak instruction: SpokenInstruction, routeProgress: RouteProgress?) -> SpokenInstruction?
}
2 changes: 1 addition & 1 deletion MapboxNavigationTests/NavigationViewControllerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ class TestableDayStyle: DayStyle {


class FakeVoiceController: RouteVoiceController {
override func speak(_ instruction: SpokenInstruction, with locale: Locale?) {
override func speak(_ instruction: SpokenInstruction, with locale: Locale?, ignoreProgress: Bool = false) {
//no-op
}

Expand Down

0 comments on commit e0339ef

Please sign in to comment.