/// <summary> /// Plays the given file to the specified channel. /// </summary> /// <param name="eventSocket">The EventSocket instance.</param> /// <param name="uuid">The Channel UUID.</param> /// <param name="file">The Path to the file to be played. Note: use forward slashes for path separators.</param> /// <param name="options">Options to customize playback.</param> /// <returns>A PlayResult.</returns> /// <exception cref="FileNotFoundException">Throws FileNotFoundException if FreeSwitch is unable to play the file.</exception>//todo: should it? public static async Task <PlayResult> Play(this EventSocket eventSocket, string uuid, string file, PlayOptions options = null) { // todo: implement options for playback eg a-leg, b-leg, both, using uuid_displace if (options == null) { options = new PlayOptions(); } try { // todo: what if applicationresult is null (hang up occurs before the application completes) var result = new PlayResult( await eventSocket.ExecuteApplication(uuid, "playback", file, loops: options.Loops) .ConfigureAwait(false)); if (!result.Success) { LogFailedApplicationResult(eventSocket, result); } return(result); } catch (TaskCanceledException ex) { return(new PlayResult(null)); } }
public async Task PlayFile(string file, Leg leg = Leg.ALeg, bool mix = false, string terminator = null) { if (!IsAnswered) { return; } if (terminator != null) { await SetChannelVariable("playback_terminators", terminator); } if (leg == Leg.ALeg) //!this.IsBridged) { await eventSocket.Play(UUID, file, new PlayOptions()); return; } // uuid displace only works on one leg switch (leg) { case Leg.Both: await Task.WhenAll( eventSocket.ExecuteApplication(UUID, "displace_session", "{0} {1}{2}".Fmt(file, mix ? "m" : string.Empty, "w"), false, false), eventSocket.ExecuteApplication(UUID, "displace_session", "{0} {1}{2}".Fmt(file, mix ? "m" : string.Empty, "r"), false, false)); break; case Leg.ALeg: await eventSocket.ExecuteApplication(UUID, "displace_session", "{0} {1}{2}".Fmt(file, mix ? "m" : string.Empty, "w"), false, false); break; case Leg.BLeg: await eventSocket.ExecuteApplication(UUID, "displace_session", "{0} {1}{2}".Fmt(file, mix ? "m" : string.Empty, "r"), false, false); break; default: throw new NotSupportedException("Leg {0} is not supported".Fmt(leg)); } }
public static async Task <ReadResult> Read(this EventSocket eventSocket, string uuid, ReadOptions options) { try { // todo: what if applicationresult is null (hang up occurs before the application completes) var result = new ReadResult( await eventSocket.ExecuteApplication(uuid, "read", options.ToString()).ConfigureAwait(false), options.ChannelVariableName); if (!result.Success) { LogFailedApplicationResult(eventSocket, result); } return(result); } catch (TaskCanceledException ex) { return(new ReadResult(null, null)); } }
public static async Task <PlayGetDigitsResult> PlayGetDigits(this EventSocket eventSocket, string uuid, PlayGetDigitsOptions options) { try { // todo: what if applicationresult is null (hang up occurs before the application completes) var result = new PlayGetDigitsResult( await eventSocket.ExecuteApplication(uuid, "play_and_get_digits", options.ToString()).ConfigureAwait(false), options.ChannelVariableName); if (!result.Success) { LogFailedApplicationResult(result); } return(result); } catch (TaskCanceledException) { return(new PlayGetDigitsResult(null, null)); } }
/// <summary> /// Performs an attended transfer. If succeded, it will replace the Bridged Channel of the other Leg. /// </summary> /// <remarks> /// See https://freeswitch.org/confluence/display/FREESWITCH/Attended+Transfer /// </remarks> /// <param name="endpoint">The endpoint to transfer to eg. user/1000, sofia/[email protected] etc</param> public Task <AttendedTransferResult> AttendedTransfer(string endpoint) { try { var tcs = new TaskCompletionSource <AttendedTransferResult>(); var subscriptions = new CompositeDisposable(); var aLegUUID = lastEvent.Headers[HeaderNames.OtherLegUniqueId]; var bLegUUID = UUID; var events = eventSocket.ChannelEvents; Log.Debug(() => "Att XFer Starting A-Leg [{0}] B-Leg [{1}]".Fmt(aLegUUID, bLegUUID)); var aLegHangup = events.Where(x => x.EventName == EventName.ChannelHangup && x.UUID == aLegUUID) .Do(x => Log.Debug(() => "Att XFer Hangup Detected on A-Leg [{0}]".Fmt(x.UUID))); var bLegHangup = events.Where(x => x.EventName == EventName.ChannelHangup && x.UUID == bLegUUID) .Do(x => Log.Debug(() => "Att XFer Hangup Detected on B-Leg [{0}]".Fmt(x.UUID))); var cLegHangup = events.Where(x => x.EventName == EventName.ChannelHangup && x.UUID != bLegUUID && x.UUID != aLegUUID) .Do(x => Log.Debug(() => "Att XFer Hangup Detected on C-Leg[{0}]".Fmt(x.UUID))); var cLegAnswer = events.Where(x => x.EventName == EventName.ChannelAnswer && x.UUID != bLegUUID && x.UUID != aLegUUID) .Do(x => Log.Debug(() => "Att XFer Answer Detected on C-Leg [{0}]".Fmt(x.UUID))); var aLegBridge = events.Where(x => x.EventName == EventName.ChannelBridge && x.UUID == aLegUUID) .Do(x => Log.Debug(() => "Att XFer Bridge Detected on A-Leg [{0}]".Fmt(x.UUID))); var cLegBridge = events.Where(x => x.EventName == EventName.ChannelBridge && x.UUID != bLegUUID && x.UUID != aLegUUID) .Do(x => Log.Debug(() => "Att XFer Bridge Detected on C-Leg [{0}]".Fmt(x.UUID))); var channelExecuteComplete = events.Where( x => x.EventName == EventName.ChannelExecuteComplete && x.UUID == bLegUUID && x.GetHeader(HeaderNames.Application) == "att_xfer"); var cAnsweredThenHungUp = cLegAnswer.And(cLegHangup) .And(channelExecuteComplete.Where( x => x.GetVariable("att_xfer_result") == "success" && x.GetVariable("last_bridge_hangup_cause") == "NORMAL_CLEARING" && x.GetVariable("originate_disposition") == "SUCCESS")); var cAnsweredThenBPressedStarOrHungUp = cLegAnswer.And(bLegHangup) .And(cLegBridge.Where(x => x.OtherLegUUID == aLegUUID)); subscriptions.Add(channelExecuteComplete.Where(x => x.GetVariable("originate_disposition") != "SUCCESS") .Subscribe( x => { Log.Debug(() => "Att Xfer Not Answered"); tcs.TrySetResult(AttendedTransferResult.Failed(x.GetVariable("originate_disposition").HeaderToEnum <HangupCause>())); })); subscriptions.Add(Observable.When(cAnsweredThenHungUp.Then((answer, hangup, execComplete) => new { answer, hangup, execComplete })) .Subscribe( x => { Log.Debug(() => "Att Xfer Rejected after C Hungup"); tcs.TrySetResult(AttendedTransferResult.Failed(FreeSwitch.HangupCause.NormalClearing)); })); subscriptions.Add(channelExecuteComplete.Where(x => !string.IsNullOrEmpty(x.GetVariable("xfer_uuids"))) .Subscribe(x => { Log.Debug(() => "Att Xfer Success (threeway)"); tcs.TrySetResult(AttendedTransferResult.Success(AttendedTransferResultStatus.Threeway)); })); subscriptions.Add(Observable.When(cAnsweredThenBPressedStarOrHungUp.Then((answer, hangup, bridge) => new { answer, hangup, bridge })) .Subscribe( x => { Log.Debug(() => "Att Xfer Succeeded after B pressed *"); tcs.TrySetResult(AttendedTransferResult.Success()); })); subscriptions.Add(Observable.When(bLegHangup.And(cLegAnswer).And(aLegBridge.Where(x => x.OtherLegUUID != bLegUUID)).Then((hangup, answer, bridge) => new { answer, hangup, bridge })) .Subscribe( x => { Log.Debug(() => "Att Xfer Succeeded after B hung up and C answered"); tcs.TrySetResult(AttendedTransferResult.Success()); })); subscriptions.Add(aLegHangup.Subscribe( x => { Log.Debug(() => "Att Xfer Failed after A-Leg Hung Up"); tcs.TrySetResult(AttendedTransferResult.Hangup(x)); })); eventSocket.ExecuteApplication(UUID, "att_xfer", endpoint, false, true) .ContinueOnFaultedOrCancelled(tcs, subscriptions.Dispose); return(tcs.Task.Then(() => subscriptions.Dispose())); } catch (TaskCanceledException) { return(Task.FromResult(AttendedTransferResult.Failed(FreeSwitch.HangupCause.None))); } }
public static Task <EventMessage> Stoptmf(this EventSocket eventSocket, string uuid) { return(eventSocket.ExecuteApplication(uuid, "spandsp_stop_dtmf")); }
public static Task <EventMessage> Say(this EventSocket eventSocket, string uuid, SayOptions options) { return(eventSocket.ExecuteApplication(uuid, "say", options.ToString())); }
public static Task <ChannelEvent> StopDtmf(this EventSocket eventSocket, string uuid) { return(eventSocket.ExecuteApplication(uuid, "spandsp_stop_dtmf")); }