Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a function for breaking through mute of the speech synthesizer. #4195

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
* MapboxMobileEvents dependency is replaced with CoreTelemetry (part of MapboxCommon). ([#4011](https://github.com/mapbox/mapbox-navigation-ios/pull/4011))
* Deprecated `NavigationEventsManager.init(activeNavigationDataSource:passiveNavigationDataSource:accessToken:mobileEventsManager:)` in favour of `NavigationEventsManager.init(activeNavigationDataSource:passiveNavigationDataSource:accessToken:)`. ([#4011](https://github.com/mapbox/mapbox-navigation-ios/pull/4011))
* Added `NavigationViewController.usesNightStyleInDarkMode` property to control whether night style is used in dark mode. ([#4143](https://github.com/mapbox/mapbox-navigation-ios/pull/4143))
* Added `SpeechSynthesizing.forceSpeak(instruction:during: locale:)` to break through mute of speech synthesizer. ([#4195](https://github.com/mapbox/mapbox-navigation-ios/pull/4195))

## v2.8.1

Expand Down
5 changes: 5 additions & 0 deletions Sources/MapboxNavigation/MultiplexedSpeechSynthesizer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ open class MultiplexedSpeechSynthesizer: SpeechSynthesizing {
currentLegProgress = legProgress
speechSynthesizers.first?.speak(instruction, during: legProgress, locale: locale)
}

public func forceSpeak(_ instruction: SpokenInstruction, during legProgress: RouteLegProgress, locale: Locale? = nil) {
currentLegProgress = legProgress
speechSynthesizers.first?.forceSpeak(instruction, during: legProgress, locale: locale)
}

public func stopSpeaking() {
speechSynthesizers.forEach { $0.stopSpeaking() }
Expand Down
21 changes: 20 additions & 1 deletion Sources/MapboxNavigation/SpeechSynthesizing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import MapboxCoreNavigation
/**
Protocol for implementing speech synthesizer to be used in `RouteVoiceController`.
*/
public protocol SpeechSynthesizing: AnyObject {
public protocol SpeechSynthesizing: AnyObject, UnimplementedLogging {

/// A delegate that will be notified about significant events related to spoken instructions.
var delegate: SpeechSynthesizingDelegate? { get set }
Expand Down Expand Up @@ -38,13 +38,32 @@ public protocol SpeechSynthesizing: AnyObject {
///
/// This method is not guaranteed to be synchronous or asynchronous. When vocalizing is finished, `voiceController(_ voiceController: SpeechSynthesizing, didSpeak instruction: SpokenInstruction, with error: SpeechError?)` should be called.
func speak(_ instruction: SpokenInstruction, during legProgress: RouteLegProgress, locale: Locale?)

/// A request to vocalize the instruction, breaking through the mute of the speech synthesizer if muted
/// - parameter instruction: an instruction to be vocalized
/// - parameter legProgress: current leg progress, corresponding to the instruction
/// - parameter locale: A locale to be used for vocalizing the instruction. If `nil` is passed - `SpeechSynthesizing.locale` will be used as 'default'.
///
/// This method is not guaranteed to be synchronous or asynchronous. When vocalizing is finished, `voiceController(_ voiceController: SpeechSynthesizing, didSpeak instruction: SpokenInstruction, with error: SpeechError?)` should be called.
func forceSpeak(_ instruction: SpokenInstruction, during legProgress: RouteLegProgress, locale: Locale?)

/// Tells synthesizer to stop current vocalization in a graceful manner
func stopSpeaking()
/// Tells synthesizer to stop current vocalization immediately
func interruptSpeaking()
}

extension SpeechSynthesizing {

/**
`UnimplementedLogging` prints a warning to standard output the first time this method is called.
*/
public func forceSpeak(_ instruction: SpokenInstruction, during legProgress: RouteLegProgress, locale: Locale?) {
logUnimplemented(protocolType: SpeechSynthesizing.self, level: .debug)
speak(instruction, during: legProgress, locale: locale)
}
}

/**
The `SpeechSynthesizingDelegate` protocol defines methods that allow an object to respond to significant events related to spoken instructions.
*/
Expand Down
5 changes: 4 additions & 1 deletion Sources/MapboxNavigation/SystemSpeechSynthesizer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ open class SystemSpeechSynthesizer: NSObject, SpeechSynthesizing {
with: nil)
return
}

forceSpeak(instruction, during: legProgress, locale: locale)
}

open func forceSpeak(_ instruction: SpokenInstruction, during legProgress: RouteLegProgress, locale: Locale? = nil) {
guard let locale = locale ?? self.locale else {
self.delegate?.speechSynthesizer(self,
encounteredError: SpeechError.undefinedSpeechLocale(instruction: instruction))
Expand Down