A Recorderis an entity that is capable of receiving audio media that comes from an AudioVideoFlowinstance and recording it to a file. Depending on the state of the attached AudioVideoFlowinstance, a Recordercan automatically start or stop.

Unlike the Playerclass, which has two modes of operation, the Recorderclass can be thought of as having only one mode of operation, which is similar to Automaticmode in the Playerclass. If an application calls the Startmethod on a Recorderinstance, nothing will be recorded until an active AudioVideoFlowinstance is attached to it. In addition, if there is no active AudioVideoFlowinstance attached to a Recorderinstance, or if the AudioVideoFlowinstance is detached or terminated, the Recorderinstance stops automatically.

If a Recorderinstance has begun recording a file, an application can cause recording to stop by calling the Stopmethod, and state changes in the attached AudioVideoFlowinstance can also cause the Recorderinstance to stop. For example, if the Stateproperty on the AudioVideoFlowinstance changes from Activeto Terminated, the Recorderinstance stops. Non-state configuration changes in the AudioVideoFlowinstance, such as Hold, Retrieve, Mute, and changing the media channel direction, do not stop the Recorderinstance. For example, if a call being recorded remains on hold for five minutes, the Recorderinstance records five minutes of silence.

A Recorderwill not record to a file with the hidden attribute. This can cause problems that are difficult to rectify, because no error message is reported in an attempt to record to a hidden file.

Caution:
Files recorded by a Recorderdevice do not support Digital Rights Management (DRM). This means that conversations recorded by a Recorderdevice can be played by any player that supports the Windows Media Audio (WMA) media format, potentially exposing personal or confidential information.

The following code example shows the steps involved in using a Recorder.

Caution:
This code example is not a complete example. Several methods, properties, and events are used in this example, but are not defined within the example.

The essential points of creating and using a Recorderinstance appear in the following steps. Each step is assocated with a line of code that is preceded by a comment with a number in it.

  1. Create a Recorderinstance, using the constructor for this class.

  2. Attach the flow to the recorder, using the AttachFlowmethod on the Recorderclass.

  3. Create the object that receives the recording, using the WmaFileSinkconstructor. The parameter to this constructor is a string that contains the name of the WMA file that will be created. As previously mentioned, the file should not be a hidden file.

  4. Register for the StateChangedevent.

  5. Call the recorder’s SetSinkmethod, which informs the recorder of where the recorded data should go.

  6. Start the recorder, using the Startmethod on the Recorderinstance.

  7. Stop the recorder, using the Stopmethod on the Recorderinstance.

  8. Detach the flow from the Recorderinstance, using the DetachFlowmethod.

Copy Code
public void Run()
{

  // Initialize and start up the platform.
  ClientPlatformSettings clientPlatformSettings = new
ClientPlatformSettings(_applicationName,
Microsoft.Rtc.Signaling.SipTransportType.Tls);
  collabPlatform = new
CollaborationPlatform(clientPlatformSettings);
  collabPlatform.BeginStartUp(EndPlatformStartup, _collabPlatform);

  // Sync; wait for the startup to complete.
  autoResetEvent.WaitOne();

  // Initialize and register the endpoint, using the credentials of
the user the application will be acting as.
  UserEndpointSettings userEndpointSettings = new
UserEndpointSettings(_userURI, _userServer);
  userEndpointSettings.Credential = _credential;
  userEndpoint = new UserEndpoint(_collabPlatform,
userEndpointSettings);
  userEndpoint.BeginEstablish(EndEndpointEstablish, _userEndpoint);

  // Sync; wait for the registration to complete.
  autoResetEvent.WaitOne();


  // Set up the conversation and place the call.
  ConversationSettings convSettings = new ConversationSettings();
  convSettings.Priority = _conversationPriority;
  convSettings.Subject = _conversationSubject;
  // Conversation represents a collection of modalities in the
context of a dialog with one or multiple callees.
  Conversation conversation = new Conversation(_userEndpoint,
_calledParty, convSettings);

  _audioVideoCall = new AudioVideoCall(conversation);

  // Call: StateChanged: Only hooked up for logging.
  _audioVideoCall.StateChanged += new
EventHandler<CallStateChangedEventArgs>(audioVideoCall_StateChanged);

  // Subscribe to the AudioVideoFlowConfigurationRequested event;
the flow will be used to send the media.
  // Ultimately, as a part of the callback, the media will be
sent/received.
  _audioVideoCall.AudioVideoFlowConfigurationRequested += new
EventHandler<AudioVideoFlowConfigurationRequestedEventArgs>(audioVideoCall_FlowConfigurationRequested);



// Place the call to the remote party.
  _audioVideoCall.BeginEstablish(EndCallEstablish,
_audioVideoCall);

  // Sync; wait for the call to complete.
  autoResetEvent.WaitOne();

  // Sync; wait for the AudioVideoFlow to go Active.
  autoResetAVFlowActiveEvent.WaitOne();

  // Set up a recorder to record the audio from the remote side.
  // 1) Create a recorder.
  Recorder recorder = new Recorder();
  // 2) Attach the flow to the recorder.
  recorder.AttachFlow(_audioVideoFlow);

  // 3) Register for StateChanged event.
  recorder.StateChanged += new
EventHandler<RecorderStateChangedEventArgs>(recorder_StateChanged);

  // 4) Create a WmaFileSink in which to record. 
  WmaFileSink sink = new WmaFileSink("recording.wma");
  // 5) Inform the recorder about the recording destination.
  recorder.SetSink(sink);

  // 6) Start the recorder.
  recorder.Start();

  Thread.Sleep(9000);

  // 7) Stop the recorder.
  recorder.Stop();

  // 8) Detach the flow from the recorder.
  recorder.DetachFlow();

  collabPlatform.BeginShutdown(EndPlatformShutdown,
_collabPlatform);

  // Wait for shutdown to occur.
  autoResetShutdownEvent.WaitOne();
}

Recorder Constructors

The Recorderclass has the following constructor.

Copy Code
// Creates a new instance of the Recorder class.
public Recorder();

Recorder Properties

The following are the public properties on the Recorderclass.

Copy Code
// Gets the Recorder state.
public RecorderState State {get;}

// Gets the destinatation to be recorded to, by the Recorder.
public MediaSink Sink {get;}

// Gets the attached AudioVideoFlow.
public AudioVideoFlow AudioVideoFlow {get;}

Recorder Methods

The following are the public methods on the Recorderclass.

Copy Code
// Starts recording media from a session.
// Can be used to initiate a new recording or to resume a paused
recording.
public void Start();

// Stops recording.
public void Stop();

// Pauses recording. To resume recording, call Start.
public void Pause();

// Sets the mode of the Recorder.
public void SetMode(RecorderMode mode);

// Sets the sink for this Recorder.
public void SetSink(MediaSink sink);

// Removes this Recorder’s sink.
public void RemoveSink();

// Attaches an AudioVideoFlow.
public void AttachFlow(AudioVideoFlow audioVideoFlow);

// Detaches an AudioVideoFlow.
// If there is no AudioVideoFlow attached to the Recorder, this
method simply returns.
public void DetachFlow();

Startthrows InvalidOperationExceptionif MediaSinkis null, and throws OperationFailureExceptionfor several reasons, including I/O errors.

SetSinkthrows ArgumentNullExceptionif sinkis null, and throws InvalidOperationExceptionif the Recorderis already started.

AttachFlowthrows ArgumentNullExceptionif its AudioVideoFlowargument is null, and throws InvalidOperationExceptionif its argument is already attached to any Recorder.

Recorder Events

The following are the public events on the Recorderclass.

Copy Code
// Raised to notify an application that Recorder state has changed.
public event EventHandler<RecorderStateChangedEventArgs>
StateChanged;