Prompt() with options
Hi,
I don't know if this is the right place for general usage questions. First time using this library.
I've tried the example here with play() and it works OK:
https://github.com/CyCoreSystems/ari/blob/main/_examples/play/main.go
Now I'd like to replace Play() with Prompt(), but I'd also like to limit the "interrupt DTMF keys" to a subset of AllDTMF as seen here:
https://github.com/CyCoreSystems/ari/blob/main/ext/play/play.go
say, "01234#". In other words, if there's a match, playback should be immediately interrupted and I should be able to know which digit was pressed.
I think I need to define an Options struct as seen here:
https://github.com/CyCoreSystems/ari/blob/main/ext/play/options.go
and then pass it to Prompt() as 3rd parameter. Then I should be able to get the pressed digit in play.Result.DTMF.
Sorry for the rookie question, but a quick example on how to set the options, pass them to Prompt() and read the pressed DTMF would be very useful.
Regards
[EDIT]
I tried this snippet:
res, err := play.Prompt(ctx, h, play.URI("sound:googletts/d6fe29440ba3ac62606c8c3e5f93943e"),
play.MatchHash(), // match any digits until hash
play.Replays(3), // repeat prompt up to three times, if no match
).Result()
if err != nil {
log.Error("failed to play sound", "error", err)
return
}
if res.MatchResult == play.Complete {
log.Info("Got valid, terminated DTMF entry", res.DTMF)
// hash is automatically trimmed from res.DTMF
}
I think I need to use MatchDiscrete() for a custom list of digits, right?
[EDIT]
I tried this:
res, err := play.Prompt(ctx, h,
play.URI("sound:mysounbd"),
play.MatchDiscrete([]string{"0", "1", "2", "3", "4", "5", "#"}),
).Result()
If I press any one of those digits during audio playback, all's well. However, if I hit '9' which isn't in the list the audio playback is interrupted (when it shouldn't according to https://github.com/CyCoreSystems/ari/blob/a3f6a369a00cb6f8a1c569928716680fdffbd7f4/ext/play/options.go#L390) and I get 0 / nil for res.MatchResult.
[EDIT]
Either I'm misusing/misunderstanding the code or there's a bug:
list := []string{"0", "1", "2", "3", "4", "5", "#"}
res, err := play.Prompt(ctx, h,
play.URI("sound:mysound"),
play.MatchFunc(func(pat string) (string, play.MatchResult) {
var maxLen int
for _, t := range list {
if t == pat {
return pat, play.Complete
}
if len(t) > maxLen {
maxLen = len(t)
}
}
if len(pat) > maxLen {
return pat, play.Invalid
}
log.Info("MatchFunc will return incomplete or 0", "incomplete", play.Incomplete)
return pat, 0
//return pat, play.Incomplete
}),
).Result()
The match function returns 0 if I press a digit that does not match "list" (eg. "9"). I'm expecting the audio playback to continue when this happens. Instead, the playback is interrupted. Why is the playback of "sound:mysound" interrupted if MatchFunc returns 0 or play.Incomplete?
Prompt() will always terminate the audio when the prompt terminates.
If you need to simply ignore digits not of a set, you'll want to use MatchFunc and implement your own system.
You could also (with your example, using a '#' terminator), post-process the matched DTMF string to elide the ignored digits.
If I were you, though, I would just implement my own MatchFunc (func(string) (string, MatchResult))).
If I were you, though, I would just implement my own MatchFunc (
func(string) (string, MatchResult))).
I did that in my last "EDIT" of my first post. I redefined
play.MatchFunc(func(pat string) (string, play.MatchResult)
for Prompt().
What should MatchFunc return if I don't want Prompt() to terminate (thus terminating the audio)?
Thanks
play.Incomplete: https://pkg.go.dev/github.com/CyCoreSystems/ari/ext/play#MatchResult
This indicates a match is not yet found, so Prompt should not yet terminate.
play.Incomplete is 0, right?
If so, this is why I was asking the following question in my first post:
Why is the playback of "sound:mysound" interrupted if MatchFunc returns 0 or play.Incomplete?
I'm repasting the code here for clarity:
list := []string{"0", "1", "2", "3", "4", "5", "#"}
res, err := play.Prompt(ctx, h,
play.URI("sound:mysound"),
play.MatchFunc(func(pat string) (string, play.MatchResult) {
var maxLen int
for _, t := range list {
if t == pat {
return pat, play.Complete
}
if len(t) > maxLen {
maxLen = len(t)
}
}
if len(pat) > maxLen {
return pat, play.Invalid
}
log.Info("MatchFunc will return incomplete or 0", "incomplete", play.Incomplete)
return pat, 0
//return pat, play.Incomplete
}),
).Result()
Hmm... yeah, that's definitely how it is supposed to work: play.Incomplete means that the playback sequence does not get signaled to stop the playback, so it should continue playing.
For a sanity check, can you play a sequence of multiple files, use play.MatchNone(), and see what happens?