/// <summary> /// Plays the provided audio source to the A-Leg. /// Dispose the returned token to cancel playback. /// </summary> /// <param name="file">The audio source.</param> /// <returns>An <seealso cref="IDisposable"/> which can be disposed to stop the audio.</returns> public async Task <IDisposable> PlayUntilCancelled(string file) { if (!CanPlayBackAudio) { Log.Warn(() => "Channel [{0}] attempted to play hold music when not answered".Fmt(UUID)); return(Task.FromResult(new DisposableAction())); } // essentially, we'll do a playback application call without waiting for the ChannelExecuteComplete event // the caller can .Dispose() the returned token to do a uuid_break on the channel to kill audio. await eventSocket.SendCommand(string.Format("sendmsg {0}\ncall-command: execute\nexecute-app-name: playback\nexecute-app-arg:{1}\nloops:-1", UUID, file)); var cancellation = new DisposableAction( async() => { if (!CanPlayBackAudio) { return; } try { await eventSocket.Api("uuid_break", UUID); } catch (Exception ex) { Log.ErrorException("Error calling 'api uuid_break {0}'".Fmt(UUID), ex); } }); return(cancellation); }