I am new to UCMA and I am learning as I go through examples. I am trying to build 2 Lync clients A and B with the scenario as follows,
- A calls B
- B answers
- A plays audio
- B records it using Recorder.
I am stuck at trying to record the call at B. For B its an incoming call. I need to attach the audiovideoflow to the recorder, but I am not sure on how to do it. I will appreciate any help. Apologies on the unformatted code, I am not sure how to format it properly, I tried.
Thanks. Kris
Client B Code:
- Accepts an incoming call
Records the media received in the incoming call. ***This is the part I have trouble
using System; using System.Threading; using Microsoft.Rtc.Collaboration; using Microsoft.Rtc.Collaboration.AudioVideo; using Microsoft.Rtc.Signaling; using Microsoft.Rtc.Collaboration.Lync;
namespace Microsoft.Rtc.Collaboration.LyncUAS { public class LyncUAS { #region Locals private LyncUASConfigurationHelper _helper; private UserEndpoint _userEndpoint; private AudioVideoCall _audioVideoCall; private AudioVideoFlow _audioVideoFlow; private Conversation _incomingConversation;
//Wait handles are only present to keep things synchronous and easy to read. private AutoResetEvent _autoResetEvent = new AutoResetEvent(false); private EventHandler<AudioVideoFlowConfigurationRequestedEventArgs> _audioVideoFlowConfigurationRequestedEventHandler; private EventHandler<MediaFlowStateChangedEventArgs> _audioVideoFlowStateChangedEventHandler; private AutoResetEvent _waitForAudioVideoCallEstablishCompleted = new AutoResetEvent(false); private AutoResetEvent _waitForAudioVideoFlowStateChangedToActiveCompleted = new AutoResetEvent(false); private AutoResetEvent _waitForPrepareSourceCompleted = new AutoResetEvent(false); #endregion #region Methods /// <summary> /// Instantiate and run the DeclineIncomingCall quickstart. /// </summary> /// <param name="args">unused</param> public static void Main(string[] args) { LyncUAS lyncUAS = new LyncUAS(); lyncUAS.Run(); } private void Run() { string filename = "received.wma"; _helper = new LyncUASConfigurationHelper(); // Create a user endpoint, using the network credential object // defined above. _userEndpoint = _helper.CreateEstablishedUserEndpoint("Lync UAS" /*endpointFriendlyName*/); _userEndpoint.RegisterForIncomingCall<AudioVideoCall>(On_AudioVideoCall_Received); Console.WriteLine("Waiting for incoming call..."); _autoResetEvent.WaitOne(); Console.WriteLine("came after call is connected"); //start recording for audio. Recorder recorder = new Recorder(); recorder.StateChanged += new EventHandler<RecorderStateChangedEventArgs>(recorder_StateChanged); recorder.VoiceActivityChanged += new EventHandler<VoiceActivityChangedEventArgs>(recorder_VoiceActivityChanged);
//**********This is the issue, currently _audioVideoFlow is null, it is not attached to the flow //So this will fail, how to attach _audioVideoFlow to an incoming call ?? HELP !!!
// recorder.AttachFlow(_audioVideoFlow); ------------> HELP! WmaFileSink sink = new WmaFileSink(filename); recorder.SetSink(sink); recorder.Start(); Console.WriteLine("Started Recording ..."); _autoResetEvent.WaitOne(); recorder.Stop(); Console.WriteLine("Stopped Recording ..."); recorder.DetachFlow(); Console.WriteLine("Exiting"); Thread.Sleep(2000); } private void audioVideoFlow_StateChanged(object sender, MediaFlowStateChangedEventArgs e) { Console.WriteLine("Flow state changed from " + e.PreviousState + " to " + e.State); //When flow is active, media operations can begin if (e.State == MediaFlowState.Active) { // Flow-related media operations normally begin here. _waitForAudioVideoFlowStateChangedToActiveCompleted.Set(); } // call sample event handler if (_audioVideoFlowStateChangedEventHandler != null) { _audioVideoFlowStateChangedEventHandler(sender, e); } } void recorder_VoiceActivityChanged(object sender, VoiceActivityChangedEventArgs e) { Console.WriteLine("Recorder detected " + (e.IsVoice ? "voice" : "silence") + " at " + e.TimeStamp); } void recorder_StateChanged(object sender, RecorderStateChangedEventArgs e) { Console.WriteLine("Recorder state changed from " + e.PreviousState + " to " + e.State); } void On_AudioVideoCall_Received(object sender, CallReceivedEventArgs<AudioVideoCall> e) { //Type checking was done by the platform; no risk of this being any // type other than the type expected. _audioVideoCall = e.Call; // Call: StateChanged: Only hooked up for logging, to show the call // state transitions. _audioVideoCall.StateChanged += new EventHandler<CallStateChangedEventArgs>(_audioVideoCall_StateChanged); _incomingConversation = new Conversation(_userEndpoint); Console.WriteLine("Call Received! From: " + e.RemoteParticipant.Uri + " Toast is: " +e.ToastMessage.Message); _audioVideoCall.BeginAccept( ar => { try { _audioVideoCall.EndAccept(ar); Console.WriteLine("Call must be connected at this point. "+_audioVideoCall.State); _autoResetEvent.Set(); } catch (RealTimeException ex) { Console.WriteLine(ex); } }, null); } //Just to record the state transitions in the console. void _audioVideoCall_StateChanged(object sender, CallStateChangedEventArgs e) { Console.WriteLine("Call has changed state. The previous call state was: " + e.PreviousState + " and the current state is: " + e.State); if (e.State == CallState.Terminated) { Console.WriteLine("Shutting down"); _autoResetEvent.Set(); _helper.ShutdownPlatform(); } } #endregion }
}