<commit_before>package audio

import (
	"errors"
	"time"

	"github.com/CyCoreSystems/ari"
	uuid "github.com/satori/go.uuid"
	"golang.org/x/net/context"
)

// AllDTMF is a string which contains all possible
// DTMF digits.
const AllDTMF = "0123456789ABCD*#"

// PlaybackStartTimeout is the time to allow for Asterisk to
// send the PlaybackStarted before giving up.
var PlaybackStartTimeout = 1 * time.Second

// MaxPlaybackTime is the maximum amount of time to allow for
// a playback to complete.
var MaxPlaybackTime = 10 * time.Minute

// Play plays the given media URI
func Play(ctx context.Context, p Player, mediaURI string) (st Status, err error) {
	pb := PlayAsync(ctx, p, mediaURI)

	<-pb.Stopped()

	st, err = pb.Status(), pb.Err()
	return
}

// PlayAsync plays the audio asynchronously and returns a playback object
func PlayAsync(ctx context.Context, p Player, mediaURI string) *Playback {

	var pb Playback

	pb.startCh = make(chan struct{})
	pb.stopCh = make(chan struct{})
	pb.status = InProgress
	pb.err = nil
	pb.ctx, pb.cancel = context.WithCancel(ctx)

	// register for events on the ~~playback~~ player handle. This means
	// we have to filter the events using the evnentual playback handle.
	playbackStarted := p.Subscribe(ari.Events.PlaybackStarted)
	playbackFinished := p.Subscribe(ari.Events.PlaybackFinished)

	//TODO: confirm whether we need to listen on bridge events if p Player is a bridge
	hangup := p.Subscribe(ari.Events.ChannelHangupRequest, ari.Events.ChannelDestroyed)

	go func() {
		defer func() {
			playbackStarted.Cancel()
			playbackFinished.Cancel()
			hangup.Cancel()
			close(pb.stopCh)
		}()

		id := uuid.NewV1().String()
		pb.handle, pb.err = p.Play(id, mediaURI)
<commit_msg>ext/audio - call play outside goroutine<commit_after>package audio

import (
	"errors"
	"time"

	"github.com/CyCoreSystems/ari"
	uuid "github.com/satori/go.uuid"
	"golang.org/x/net/context"
)

// AllDTMF is a string which contains all possible
// DTMF digits.
const AllDTMF = "0123456789ABCD*#"

// PlaybackStartTimeout is the time to allow for Asterisk to
// send the PlaybackStarted before giving up.
var PlaybackStartTimeout = 1 * time.Second

// MaxPlaybackTime is the maximum amount of time to allow for
// a playback to complete.
var MaxPlaybackTime = 10 * time.Minute

// Play plays the given media URI
func Play(ctx context.Context, p Player, mediaURI string) (st Status, err error) {
	pb := PlayAsync(ctx, p, mediaURI)

	<-pb.Stopped()

	st, err = pb.Status(), pb.Err()
	return
}

// PlayAsync plays the audio asynchronously and returns a playback object
func PlayAsync(ctx context.Context, p Player, mediaURI string) *Playback {

	var pb Playback

	pb.startCh = make(chan struct{})
	pb.stopCh = make(chan struct{})
	pb.status = InProgress
	pb.err = nil
	pb.ctx, pb.cancel = context.WithCancel(ctx)

	// register for events on the ~~playback~~ player handle. This means
	// we have to filter the events using the evnentual playback handle.
	playbackStarted := p.Subscribe(ari.Events.PlaybackStarted)
	playbackFinished := p.Subscribe(ari.Events.PlaybackFinished)

	//TODO: confirm whether we need to listen on bridge events if p Player is a bridge
	hangup := p.Subscribe(ari.Events.ChannelHangupRequest, ari.Events.ChannelDestroyed)

	id := uuid.NewV1().String()
	pb.handle, pb.err = p.Play(id, mediaURI)

	go func() {
		defer func() {
			playbackStarted.Cancel()
			playbackFinished.Cancel()
			hangup.Cancel()
			close(pb.stopCh)
		}()

		// wait to check error here so
		// subscriptions are cleaned up
{'fraction_non_alphanumeric': 0.1091937765205092, 'fraction_numerical': 0.007920792079207921, 'mean_word_length': 3.966292134831461, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3779675', 'n_tokens_mistral': 1227, 'n_tokens_neox': 1157, 'n_words': 370}