Share via


Player

This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.

The Player class represents an entity that is capable of playing media to one or more media flows, and as such, provides a simple, scalable way to play an audio segment in a Windows Media Audio (WMA) file to multiple listeners. A Player instance renders the media that is represented by an instance of a subclass of the MediaSource abstract base class. The output from a Player instance goes to one or more AudioVideoFlow instances.

A Player acts as a pointer to a MediaSource object, and determines the current position to play in the media.

The Player class has two modes of operation:

  • Automatic (the default)

    In Automatic mode, the behavior of a Player instance depends on the state of the attached AudioVideoFlow instance. If an application calls the Start method on the Player instance, the State property on the Player instance changes to Started, but nothing is played until there is an active AudioVideoFlow instance attached to the Player instance (that is, until the State property on the AudioVideoFlow instance is Active).

    If the last active AudioVideoFlow instance is detached or terminated while a Player instance in Automatic mode is playing, the Player instance stops automatically.

  • Manual

    In Manual mode, a Player instance can operate with or without an attached AudioVideoFlow instance, although no one would be able to listen to the file being played if there were no attached AudioVideoFlow instance. If the last active AudioVideoFlow instance is detached or terminated while a Player instance in Manual mode is playing, the Player instance continues playing. In this regard, a Player instance in Manual mode behaves like a CD player whose speakers are disconnected.

The simplest arrangement is a single Player instance with a single attached AudioVideoFlow instance, as shown in the following illustration.

Single player, single AudioVideoFlow instance

Dd253381.26522cfd-5b54-48a4-8d4d-911d470b479c(en-us,office.13).jpg

Another arrangement is to have a single Player instance that has multiple AudioVideoFlow instances, as shown in the following illustration. In this arrangement, the audio media to be played has a single play position and all attached AudioVideoFlow instances receive exactly the same audio simultaneously. This capability is useful for providing Music on Hold, or for broadcasting audio to multiple listeners.

Single Player, multiple AudioVideoFlow instances

Dd253381.e2c80edd-f56f-41dc-b2d1-4932de97aa47(en-us,office.13).jpg

A third arrangement is to have multiple Player instances with multiple attached AudioVideoFlow instances, as shown in the following illustration. Each Player instance determines a different playing point in the media source. The AudioVideoFlow instances attached to a given Player instance (for example, AudioVideoFlow 1 and AudioVideoFlow 2 that are attached to Player 1) receive the same audio at the same time, but AudioVideoFlow instances attached to different Player instances receive different audio segments at any given time (for example, AudioVideoFlow 1 and AudioVideoFlow 3 that are attached, respectively, to Player 1 and Player 2). This capablity is useful for providing Welcome messages to listeners when they arrive at a conference.

Multiple Player instances, multiple AudioVideoFlow instances

Dd253381.4134866d-064e-4e76-a184-90d4e8823bd9(en-us,office.13).jpg

The Player class is scalable. Together with a MediaSource object, it will decide the best way to store data. For example, if MediaSource is a file, raw data will be read only if new channel encoding (for example, SIREN or RTAudio) is needed. In buffered mode, the MediaSource caches encoded versions of media. A MediaSource can be opened in buffered mode (MediaSourceOpenMode.Buffered) or in unbuffered mode (MediaSourceOpenMode.Unbuffered). When an encoded stream is reused, playing the cached stream provides significant performance gains.

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

Warning

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 Player instance are shown 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 Player instance, using the constructor for this class.

  2. Attach the flow to the player, using the AttachFlow method on the Player class.

  3. Register for the player’s StateChanged event.

  4. Load the file that is to be played into memory by creating a WmaFileSource instance. The string parameter is the name of the WMA file to be played.

  5. Prepare the source file, using the BeginPrepareSource method on the WmaFileSource instance. The caller can specify whether the file is to be opened in Buffered mode or in Unbuffered mode. In the example code, the argument to EndPrepareSource is the return value from BeginPrepareSource.

  6. Set the player’s mode, using the SetMode method. In the example, the mode is set to Automatic, which means that the player will begin playing only when the State of the attached AutoVideoFlow instance is Active. The Player stops when it reaches the end of the file or when there are no attached AudioVideoFlow instances that are Active. If the mode were set to Manual, the player would start playing immediately.

  7. Inform the player about the source of the media it will play, using the SetSource method.

  8. Start the player, using the player’s Start method.

  9. Pause the player, using the player’s Pause method. This step is shown only to demonstrate how to pause the player.

  10. Restart the player after it was paused, using the Start method.

  11. Stop the player, using the player’s Stop method.

  12. Close the source, using the Close method on the WmaFileSource instance. An application must close the source when it is not longer needed. A source that is not closed can result in a memory leak.

  13. Detach the flow, using the player’s DetachFlow method.

public void Run()
{
  // Initialize and startup 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/recieved.
  _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 goes Active
  _autoResetAVFlowActiveEvent.WaitOne();

  // 1) Create a Player and attach to AVFlow
  Player player = new Player();
  // 2) Attach the Player to the AVFlow
  player.AttachFlow(_audioVideoFlow);

  // 3) Subscribe to player StateChanged event, including the play completed event. 
  player.StateChanged += new EventHandler<PlayerStateChangedEventArgs>(player_StateChanged);

  // 4) Load the file into memory
    WmaFileSource source = new WmaFileSource("startup.wma");
  
  // 5) Prepare the source for the player.
  source.EndPrepareSource(source.BeginPrepareSource(MediaSourceOpenMode.Buffered, null, null));

  // 6) Set the play mode. In automatic mode, player will start playing only when the flow is in the active state.
  // In manual mode, player will start playing immediately.
  player.SetMode(PlayerMode.Automatic);

  // 7) Inform the player about the source.
  player.SetSource(source);

  // 8) Start the player.
    player.Start();

    Thread.Sleep(2000);

  // 9) Pause the player.
    player.Pause();

    Thread.Sleep(2000);

  // 10) Restart the player.
  player.Start();

    Thread.Sleep(5000);

  // 11) Stop the player.
  player.Stop();

  // 12) Source must be closed after it is no longer needed, otherwise memory will not be released even after garbage collection.
  source.Close();

  // 13) Player must be detached from the flow, otherwise if the player is rooted, it will keep the flow in memory.
  player.DetachFlow(_audioVideoFlow);


  _collabPlatform.BeginShutdown(EndPlatformShutdown, _collabPlatform);

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

Player Constructors

The Player class has the following constructors.

// Creates a new instance of the Player class with State set to Stopped.
public Player();

Player Properties

The following are the public properties on the Player class.

// Gets the media to be played by the Player.
public MediaSource Source {get;}

// Gets the state of the Player.
public PlayerState State {get;}

// Gets the AudioVideoFlows attached to the player.
public ReadOnlyCollection<AudioVideoFlow> AudioVideoFlows {get;}

// Gets the current mode of the Player.
public PlayerMode Mode {get;}

Player Methods

The following are the public methods on the Player class.

// Sets the mode of the Player, which can be either Automatic or Manual.
public void SetMode(PlayerMode mode);

// Sets the MediaSource for the Player.
public void SetSource(MediaSource source);

// Removes the sink from this Player.
public void RemoveSource();

// Attaches an AudioVideoFlow.
// If there is already an AudioVideoFlow instance attached, the method merely returns.
public void AttachFlow(AudioVideoFlow audioVideoFlow);

// Detaches an AudioVideoFlow.
// If the Player is not already attached to a flow, the method merely returns.
public void DetachFlow(AudioVideoFlow audioVideoFlow);

// Plays the attached MediaSource.
public void Start();

// Stops playing the MediaSource and
// resets the current playing position to the beginning of the media.
public void Stop();

// Pauses playing MediaSource, keeping the current playing position.
// Throws InvalidOperationException if MediaSource is not attached or there are no sessions bound.
public void Pause();

// Allows the current play position to be moved. Method can be called in any state. 
// The argument value can be positive (to move forward) or negative (to move backward.
public void Skip(int milliSeconds);

SetSource throws InvalidOperationException if State on the Player is not Stopped.

AttachFlow throws ArgumentNullException if the AudioVideoFlow argument is null.

DetachFlow throws ArgumentNullException if the AudioVideoFlow argument is null.

Start throws InvalidOperationException if Source is null, unprepared, or closed, or if the Player is already in the Started state, and throws OperationFailureException for several reasons, including an overloaded system.

Pause throws InvalidOperationException if the Player is not in the Started state.

Player Events

The following are the public events on the Player class.

// Raised to notify an application that the Player state changed.
public event EventHandler<PlayerStateChangedEventArgs> StateChanged;