Skip to content

Prompt() with options #181

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

Open
vieridipaola opened this issue Apr 3, 2025 · 5 comments
Open

Prompt() with options #181

vieridipaola opened this issue Apr 3, 2025 · 5 comments

Comments

@vieridipaola
Copy link

vieridipaola commented Apr 3, 2025

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

// MatchDiscrete indicates that the playback should be considered Matched and terminated if
)
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?

@Ulexus
Copy link
Member

Ulexus commented Apr 19, 2025

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))).

@vieridipaola
Copy link
Author

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

@Ulexus
Copy link
Member

Ulexus commented Apr 28, 2025

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.

@vieridipaola
Copy link
Author

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()

@Ulexus
Copy link
Member

Ulexus commented May 1, 2025

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants