Skip to content

Use voice instructions from server#614

Merged
bsudekum merged 18 commits into
masterfrom
voice-instructions
Oct 18, 2017
Merged

Use voice instructions from server#614
bsudekum merged 18 commits into
masterfrom
voice-instructions

Conversation

@bsudekum
Copy link
Copy Markdown
Contributor

@bsudekum bsudekum commented Sep 14, 2017

Need mapbox/mapbox-directions-swift#175 merged first

Todo:

  • Better handle steps with only less than 3 announcements (right now, a high alert assumes there are 3 announcements)
  • Figure out the future of Alerts
  • Test, figure out where there are gaps between server and local instruction creation.

/cc @mapbox/guidance @1ec5 @frederoni @ericrwolfe

@1ec5
Copy link
Copy Markdown
Contributor

1ec5 commented Sep 14, 2017

Figure out the future of Alerts

🚮

@bsudekum
Copy link
Copy Markdown
Contributor Author

@1ec5 should we just do an index?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plain text instruction is still needed for the AVSpeechSynthesizer fallback. I think it would be reasonable to pass the whole VoiceInstruction object into this method.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is userDistance still needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to keep spokenInstructionFormatter.string around for testing and comparison, so yes still needed.

@1ec5
Copy link
Copy Markdown
Contributor

1ec5 commented Sep 14, 2017

should we just do an index?

I guess it depends what our customization story will be. In the future, how will custom milestones interact with the preset ones provided by the API? Would the API be able to add more or fewer than three announcements for a particular step if necessary?

As I see it, the main use case for exposing alert levels publicly was to allow developers to time UI changes around the announcements. We can meet that need by calling a delegate method whenever an announcement will be spoken or has been spoken; we’d need to pass in some way of indicating which announcement was spoken, and that information should be pretty closely tied to the API’s way of referring to the announcements. The API doesn’t currently expose any reliable way to determine the urgency of an announcement, other than its position in the array.

Other current uses of alerts should transition over to the much more flexible RouteProgress class.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s pretty weird that RouteController is observing for notifications posted by itself. Can we call these methods directly wherever we’re posting the notifications?

Observing oneself is a little risky since failing to remove the observer for whatever reason would be guaranteed to leak memory. (We’re correctly calling removeObserver(_:) in suspendNotifications(), but it’s still risky.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's fix this in it's own PR.

Comment thread MapboxCoreNavigation/Constants.swift Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A notification should never have “should” in its name: rename this constant to RouteControllerDidPassVoiceInstructionPoint or something along those lines.

A delegate method can have “should” – that would indicate that the method returns a Boolean that controls whether something happens or not. But a notification observer is never able to control the program flow.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a trap. We don’t currently document that NavigationRouteOptions or includesVoiceInstructions must be used with this library. In fact, the readme currently omits any mention of NavigationRouteOptions. We should either devise a graceful fallback strategy or fail upfront whenever NavigationViewController is created without the necessary route options. Either way, we need to update the documentation to use NavigationRouteOptions.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don’t currently document that NavigationRouteOptions or includesVoiceInstructions must be used with this library.

Tracking a documentation update in #630. Unless we remove this requirement, I’d consider #630 to block this PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn’t we continue to track this distance? Seems like it would continue to be useful for developers at least.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's cut it if it's not used.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this code live on RouteLegProgress if it’s specific to the current step?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will render the volume and speaking rate options nonfunctional. What should we do about those options until API support for them lands?

@ksummerill
Copy link
Copy Markdown

cc @ksummerill to keep 👀 on this for a customer

@bsudekum bsudekum force-pushed the voice-instructions branch 3 times, most recently from 10fb598 to f2c31c1 Compare September 19, 2017 18:30
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With my security hat on, this seems like it would enable someone to break the navigation SDK simply by renaming a road to something like <speak> or </speak>. Using a proper XML parser would be best, although if we’re absolutely certain that the Directions API will be giving us a document with <speak> as the root element, then we could address the security concern by restricting finding-and-replacing only at the beginning and end of the string.

Comment thread MapboxCoreNavigation/Constants.swift Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since alert levels are no more, describe this notification in terms of the user passing an ideal point at which to announce an upcoming maneuver.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to currentSpokenInstruction for consistency with currentStep, currentLeg, etc.

Comment thread MapboxCoreNavigation/Constants.swift Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to RouteControllerDidPassSpokenInstructionPoint for consistency. Can you look through the PR for other places that should say “spoken” instead of “voice”?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to nest <prosody> tags in SSML? I could imagine a future in which the Directions API decides to pronounce some portion of an instruction slightly louder than another portion.

@bsudekum bsudekum force-pushed the voice-instructions branch 3 times, most recently from bda2dcd to 109bb42 Compare September 28, 2017 21:47
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull this logic out into an extension on Locale, then get the current locale’s measurement system:

var usesMetric: Bool {
let locale = numberFormatter.locale as NSLocale
guard let measurementSystem = locale.object(forKey: .measurementSystem) as? String else {
return false
}
return measurementSystem == "Metric"
}

@bsudekum bsudekum force-pushed the voice-instructions branch 3 times, most recently from 46ab7e9 to 7472ed8 Compare October 2, 2017 23:47
@bsudekum
Copy link
Copy Markdown
Contributor Author

bsudekum commented Oct 4, 2017

In order how this PR is blocked:

Let's start powering through this list. @1ec5 @mcwhittemore can I get your eyes on Project-OSRM/osrm-text-instructions#168 today?

@bsudekum bsudekum force-pushed the voice-instructions branch from 7472ed8 to 79f20ec Compare October 4, 2017 16:16
@bsudekum
Copy link
Copy Markdown
Contributor Author

bsudekum commented Oct 4, 2017

Began working on prefetching audio instructions here. Blocked by a few PRs. voice-instructions...prefetch-audio

@bsudekum bsudekum force-pushed the voice-instructions branch from 79f20ec to 4394192 Compare October 6, 2017 17:36
@1ec5
Copy link
Copy Markdown
Contributor

1ec5 commented Oct 7, 2017

This branch is pretty far from compiling. Are you working within a CocoaPods workspace? If so, please try developing directly against the project in this repository.

@bsudekum
Copy link
Copy Markdown
Contributor Author

bsudekum commented Oct 10, 2017

Alright this is ready to go. @frederoni @1ec5 @JThramer could you 👀 this?

Scratch that, still some work to do.

@bsudekum
Copy link
Copy Markdown
Contributor Author

@1ec5 @frederoni @JThramer okay, this is now ready for review.

Copy link
Copy Markdown
Contributor

@1ec5 1ec5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks good to go, although I’m not sure if we’re planning to hold this PR until the Directions API catches up to the latest dependencies. Please test against the production API before merging.

input.text = "<speak><amazon:effect name=\"drc\"><prosody volume='\(instructionVoiceVolume)' rate='\(instructionVoiceSpeedRate)'>\(text)</prosody></amazon:effect></speak>"
let wrappedSSML = text
.replacingOccurrences(of: "^<speak\\s*(?:\\s+[^>]*)?>", with: "$0<amazon:effect name=\"drc\"><prosody volume='\(instructionVoiceVolume)' rate='\(instructionVoiceSpeedRate)'>", options: .regularExpression)
.replacingOccurrences(of: "</speak>$", with: "</prosody></amazon:effect></speak>",options: .regularExpression)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noting for posterity that we need to remove this code once the Directions API begins to add these tags itself.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@1ec5 what do you think about making this future proof-able and adding an xml parsing dependency? It might make sense to check and make sure we have all necessary keys.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I think we should introduce an XML parsing library only when we need it for a particular purpose, so that we can evaluate each candidate library based on how well it’d handle our use case. As it stands, we’re planning to have the Directions API add these tags, so the SDK won’t have any XML parsing needs for now.

*/
case arrive
}
import AVFoundation
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use AVFoundation in RouteProgress?

@bsudekum
Copy link
Copy Markdown
Contributor Author

Removed our custom tag addition code in 7254395. We'll need the new tags deployed to the Directions API before merging this.

/cc @mcwhittemore @1ec5 @ericrwolfe

@bsudekum bsudekum merged commit f44f1b5 into master Oct 18, 2017
@1ec5 1ec5 added the backwards incompatible changes that break backwards compatibility of public API label Dec 18, 2018
@1ec5 1ec5 added this to the v0.10.0 milestone Dec 18, 2018
@1ec5 1ec5 deleted the voice-instructions branch December 5, 2019 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backwards incompatible changes that break backwards compatibility of public API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants