Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / Controls / AVElementHelper.cs / 1 / AVElementHelper.cs
//----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// File: avelementhelper.cs
//
// Description: Contains the AVElementHelper class.
//
// History:
// 05/04/2004 : [....] - Added
//
//---------------------------------------------------------------------------
using MS.Internal;
using MS.Utility;
using System.Diagnostics;
using System.Windows.Threading;
using System;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Security;
using System.Security.Permissions;
namespace System.Windows.Controls
{
#region SettableState
///
/// Settable State, keeps track of what state was set and whether it has
/// been set recently.
///
internal struct SettableState
{
internal T _value;
internal bool _isSet;
internal bool _wasSet;
internal
SettableState(
T value
)
{
_value = value;
_isSet = _wasSet = false;
}
}
#endregion
#region AVElementHelper
///
/// AVElementHelper
///
internal class AVElementHelper
{
#region Constructor
///
/// Constructor, point to the corresponding MediaElement.
///
internal AVElementHelper(MediaElement element)
{
Debug.Assert((element != null), "Element is null");
_element = element;
_position = new SettableState(new TimeSpan(0));
//
// We always start off in a closed state.
//
_mediaState = new SettableState(MediaState.Close);
_source = new SettableState(null);
_clock = new SettableState(null);
_speedRatio = new SettableState(1.0);
_volume = new SettableState(0.5);
_isMuted = new SettableState(false);
_balance = new SettableState(0.0);
_isScrubbingEnabled = new SettableState(false);
_mediaPlayer = new MediaPlayer();
HookEvents();
}
#endregion
#region Internal and Private Properties / Methods
///
/// Returns the helper class given a dependency object
///
internal static AVElementHelper GetHelper(DependencyObject d)
{
MediaElement mediaElement = d as MediaElement;
if (mediaElement != null)
{
return mediaElement.Helper;
}
else
{
throw new ArgumentException(SR.Get(SRID.AudioVideo_InvalidDependencyObject));
}
}
///
/// MediaPlayer associated with the element.
///
internal MediaPlayer Player
{
get
{
return _mediaPlayer;
}
}
///
/// Base Uri to use when resolving relative Uri's
///
internal Uri BaseUri
{
get
{
return _baseUri;
}
set
{
// ignore pack URIs for now (see work items 45396 and 41636)
if (value.Scheme != System.IO.Packaging.PackUriHelper.UriSchemePack)
{
_baseUri = value;
}
else
{
_baseUri = null;
}
}
}
///
/// Allows the behavior the Media Element should have when it is unloaded
/// to be expressed. This is a method because it can have side-effects
/// (Media could start playing or pause or perform a number of other
/// actions).
///
internal
void
SetUnloadedBehavior(
MediaState unloadedBehavior
)
{
_unloadedBehavior = unloadedBehavior;
HandleStateChange();
}
///
/// Changes the loaded behavior. This is a method because it can cause
/// side effects on other properties. (It could cause me to start or
/// stop playing, for example).
///
internal
void
SetLoadedBehavior(
MediaState loadedBehavior
)
{
_loadedBehavior = loadedBehavior;
HandleStateChange();
}
///
/// Returns the current position of the media.
///
internal TimeSpan Position
{
get
{
//
// If we have been closed, position is just a cached value,
// return it.
//
if (_currentState == MediaState.Close)
{
return _position._value;
}
else
{
return _mediaPlayer.Position;
}
}
}
///
/// Sets the current position of the media. This is a method
/// and not a property because it has side effects.
///
internal
void
SetPosition(
TimeSpan position
)
{
_position._isSet = true;
_position._value = position;
//
// If the media isn't closed, then we can actually send
// this down to the unmanaged state engine. It gets
// snippy if you try to change the position when it
// is closed.
//
HandleStateChange();
}
internal MediaClock Clock
{
get
{
return _clock._value;
}
}
internal
void
SetClock(
MediaClock clock
)
{
_clock._value = clock;
//
// We don't use _wasSet for clocks because our behavior changes dramatically
// whether _value is null or not.
//
_clock._isSet = true;
HandleStateChange();
}
internal double SpeedRatio
{
get
{
return _speedRatio._value;
}
}
internal
void
SetSpeedRatio(
double speedRatio
)
{
_speedRatio._wasSet = _speedRatio._isSet = true;
_speedRatio._value = speedRatio;
HandleStateChange();
}
internal
void
SetState(
MediaState mediaState
)
{
//
// If the caller hasn't requested any loaded or unloaded behavior to be manual
// then calls to Play/Pause/Stop etc. will never take effect.
//
if (_loadedBehavior != MediaState.Manual && _unloadedBehavior != MediaState.Manual)
{
throw new NotSupportedException(SR.Get(SRID.AudioVideo_CannotControlMedia));
}
_mediaState._value = mediaState;
_mediaState._isSet = true;
HandleStateChange();
}
internal
void
SetVolume(
double volume
)
{
_volume._wasSet = _volume._isSet = true;
_volume._value = volume;
HandleStateChange();
}
internal
void
SetBalance(
double balance
)
{
_balance._wasSet = _balance._isSet = true;
_balance._value = balance;
HandleStateChange();
}
internal
void
SetIsMuted(
bool isMuted
)
{
_isMuted._wasSet = _isMuted._isSet = true;
_isMuted._value = isMuted;
HandleStateChange();
}
internal
void
SetScrubbingEnabled(
bool isScrubbingEnabled
)
{
_isScrubbingEnabled._wasSet = _isScrubbingEnabled._isSet = true;
_isScrubbingEnabled._value = isScrubbingEnabled;
HandleStateChange();
}
///
/// Hook Events when clock is created/changed
///
private void HookEvents()
{
// register the new clock events
_mediaPlayer.MediaOpened += new EventHandler(OnMediaOpened);
_mediaPlayer.MediaFailed += new EventHandler(OnMediaFailed);
_mediaPlayer.BufferingStarted += new EventHandler(OnBufferingStarted);
_mediaPlayer.BufferingEnded += new EventHandler(OnBufferingEnded);
_mediaPlayer.MediaEnded += new EventHandler(OnMediaEnded);
_mediaPlayer.ScriptCommand += new EventHandler(OnScriptCommand);
_element.Loaded += new RoutedEventHandler(this.OnLoaded);
_element.Unloaded += new RoutedEventHandler(this.OnUnloaded);
}
///
/// All state changes to the media element come through this code, we first
/// look at all of the media element properties and the loaded behavior and
/// source property to see whether to open or close the media, the we set
/// other properties that actually control media and have been cached up.
///
private
void
HandleStateChange(
)
{
//
// First, just assume that our requested actions are going to be
// the same as the media requested actions.
//
MediaState thisStateRequest = _mediaState._value;
bool openClock = false;
bool actionRequested = false;
//
// If the element is loaded
//
if (_isLoaded)
{
//
// If we have a clock, then our loaded behavior is always manual.
// The clock always wins.
//
if (_clock._value != null)
{
thisStateRequest = MediaState.Manual;
openClock = true;
}
//
// If the loaded behavior was set, it wins over whether the
// source was set or not.
//
else if (_loadedBehavior != MediaState.Manual)
{
//
// If it is manual, it doesn't override the requested state.
//
thisStateRequest = _loadedBehavior;
}
else if (_source._wasSet)
{
if (_loadedBehavior != MediaState.Manual)
{
thisStateRequest = MediaState.Play;
}
else
{
actionRequested = true;
}
}
}
else
{
//
// If the unloaded behavior is manual, it doesn't override the
// requested state,
//
if (_unloadedBehavior != MediaState.Manual)
{
thisStateRequest = _unloadedBehavior;
}
else
{
//
// For situations in which we don't received loaded and unloaded
// events, (like VisualBrush), we need to set our UnloadedBehavior
// to Manual in order to allow storyboards to be able to control
// the media element.
//
Invariant.Assert(_unloadedBehavior == MediaState.Manual);
if (_clock._value != null)
{
thisStateRequest = MediaState.Manual;
openClock = true;
}
//
// Otherwise, an action was requested, we need to take it.
//
else
{
actionRequested = true;
}
}
}
bool openedMedia = false;
//
// If the media state is anything other than close
// and the current state is closed, the media needs to be opened.
//
if ( thisStateRequest != MediaState.Close
&& thisStateRequest != MediaState.Manual)
{
//
// We shouldn't have a clock to open because this would have a state
// request of MediaState.Manual.
//
Invariant.Assert(openClock == false);
//
// If we had a clock, get rid of it now. This is to handle the case
// where UnloadedBehavior is specified after the timing engine has
// been in control.
//
if (_mediaPlayer.Clock != null)
{
_mediaPlayer.Clock = null;
}
//
// If we are currently closed, we should open. If the source property
// was assigned, we should also open.
//
if (_currentState == MediaState.Close || _source._isSet)
{
//
// ScrubbingEnabled needs to be set before opening media in
// order to get the initial scrub.
//
if (_isScrubbingEnabled._wasSet)
{
_mediaPlayer.ScrubbingEnabled = _isScrubbingEnabled._value;
_isScrubbingEnabled._isSet = false;
}
if (_clock._value == null)
{
_mediaPlayer.Open(UriFromSourceUri(_source._value));
}
openedMedia = true;
}
}
else if (openClock)
{
//
// If either we were closed before, or if a clock was re-assigned without
// a state transition, then, re-apply the clock.
//
if (_currentState == MediaState.Close || _clock._isSet)
{
//
// ScrubbingEnabled needs to be set before opening media in
// order to get the initial scrub.
//
if (_isScrubbingEnabled._wasSet)
{
_mediaPlayer.ScrubbingEnabled = _isScrubbingEnabled._value;
_isScrubbingEnabled._isSet = false;
}
_mediaPlayer.Clock = _clock._value;
_clock._isSet = false;
openedMedia = true;
}
}
//
// Otherwise, if the request is for a Close and and we aren't in a closed state,
// we need to close.
//
else if (thisStateRequest == MediaState.Close)
{
if (_currentState != MediaState.Close)
{
//
// Dis-associate the clock from the player (if it has one).
// (Otherwise, it won't let us close it).
//
_mediaPlayer.Clock = null;
_mediaPlayer.Close();
_currentState = MediaState.Close;
}
}
//
// If we either just opened the media, or if we weren't closed in the
// first place, we get to perform all of the other actions.
//
if (_currentState != MediaState.Close || openedMedia)
{
//
// If we have a position request, do it now.
//
if (_position._isSet)
{
_mediaPlayer.Position = _position._value;
_position._isSet = false;
}
//
// Do volume state changes before a play so that we don't get either
// no sound or a loud sound on the play transition.
//
if (_volume._isSet || openedMedia && _volume._wasSet)
{
_mediaPlayer.Volume = _volume._value;
_volume._isSet = false;
}
if (_balance._isSet || openedMedia && _balance._wasSet)
{
_mediaPlayer.Balance = _balance._value;
_balance._isSet = false;
}
if (_isMuted._isSet || openedMedia && _isMuted._wasSet)
{
_mediaPlayer.IsMuted = _isMuted._value;
_isMuted._isSet = false;
}
//
// In the case that openedMedia is true, we will have already
// applied the scrubbing enabled property prior to opening the
// media. This is necessary for initial scrubbing to work
//
if (_isScrubbingEnabled._isSet)
{
_mediaPlayer.ScrubbingEnabled = _isScrubbingEnabled._value;
_isScrubbingEnabled._isSet = false;
}
//
// If we are asked to play because the source was reset,
// then, start playing the media again.
//
if (thisStateRequest == MediaState.Play && _source._isSet)
{
//
// We always want to Play() and then set the SpeedRatio to
// 1. This ensures that whwn you change the source of a
// MediaElement via databinding, we start playing the
// media again.
//
_mediaPlayer.Play();
if (!_speedRatio._wasSet)
{
_mediaPlayer.SpeedRatio = 1;
}
//
// We have effectively `swallowed the "Play" request, if this is
// what finally brought us into this code path.
//
_source._isSet = false;
_mediaState._isSet = false;
}
//
// Might be missing out on a Play, Pause, or a stop.
// If the source is changed, we always want to do the
// requested action. Also, we want to mirror each call
// to Play, Pause and Stop down to the underlying player.
//
else if ( _currentState != thisStateRequest
|| (actionRequested && _mediaState._isSet))
{
switch(thisStateRequest)
{
case MediaState.Play:
_mediaPlayer.Play();
break;
case MediaState.Pause:
_mediaPlayer.Pause();
break;
case MediaState.Stop:
_mediaPlayer.Stop();
break;
case MediaState.Manual:
break;
default:
Invariant.Assert(false, "Unexpected state request.");
break;
}
//
// If we did this transition because an action was requested, make sure
// we don't do it again when we come in.
//
if (actionRequested)
{
_mediaState._isSet = false;
}
}
_currentState = thisStateRequest;
//
// Finally, if the speed ratio has been set, change it.
//
if (_speedRatio._isSet || openedMedia && _speedRatio._wasSet)
{
_mediaPlayer.SpeedRatio = _speedRatio._value;
_speedRatio._isSet = false;
}
}
}
///
/// Looks at the current uri and the base uri and uses it to determine
/// whether we should normalize the uri to the base or not.
///
private
Uri
UriFromSourceUri(
Uri sourceUri
)
{
if (sourceUri != null)
{
if (sourceUri.IsAbsoluteUri)
{
return sourceUri;
}
else if (BaseUri != null)
{
return new Uri(BaseUri, sourceUri);
}
}
return sourceUri;
}
#endregion
#region Delegates
///
/// Raised when source is changed
///
///
/// Critical: This code calls into PresentationSource.CriticalFromVisual to
/// extract presentationsource.
/// TreatAsSafe: The value is not exposed and the call simply checks to see
/// if the value is null
///
[SecurityCritical,SecurityTreatAsSafe]
internal static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.IsASubPropertyChange)
{
return;
}
AVElementHelper aveh = AVElementHelper.GetHelper(d);
aveh.MemberOnInvalidateSource(e); // call non-static
}
private void MemberOnInvalidateSource(DependencyPropertyChangedEventArgs e)
{
if (_clock._value != null)
{
throw new InvalidOperationException(SR.Get(SRID.MediaElement_CannotSetSourceOnMediaElementDrivenByClock));
}
_source._value = (Uri)e.NewValue;
_source._wasSet = _source._isSet = true;
HandleStateChange();
}
///
/// Raised when there is a error with media playback
///
private
void
OnMediaFailed(
object sender,
ExceptionEventArgs args
)
{
//
// Propagate the error to the media element.
//
_element.OnMediaFailed(sender, args);
}
///
/// Raised when media is opened
///
private
void
OnMediaOpened(
object sender,
EventArgs args
)
{
// Whenever a new file is opened the size of the MediaElement may change
_element.InvalidateMeasure();
_element.OnMediaOpened(sender, args);
}
private
void
OnBufferingStarted(
object sender,
EventArgs args
)
{
_element.OnBufferingStarted(sender, args);
}
private
void
OnBufferingEnded(
object sender,
EventArgs args
)
{
_element.OnBufferingEnded(sender, args);
}
private
void
OnMediaEnded(
object sender,
EventArgs args
)
{
_element.OnMediaEnded(sender, args);
}
private
void
OnScriptCommand(
object sender,
MediaScriptCommandEventArgs args
)
{
_element.OnScriptCommand(sender, args);
}
private
void
OnLoaded(
object sender,
RoutedEventArgs args
)
{
_isLoaded = true;
HandleStateChange();
}
private
void
OnUnloaded(
object sender,
RoutedEventArgs args
)
{
_isLoaded = false;
HandleStateChange();
}
#endregion
#region Data Members
///
/// MediaPlayer
///
private MediaPlayer _mediaPlayer;
///
/// UIElement that owns this helper
///
private MediaElement _element;
private Uri _baseUri;
private MediaState _unloadedBehavior = MediaState.Close;
private MediaState _loadedBehavior = MediaState.Play;
private MediaState _currentState = MediaState.Close;
private bool _isLoaded = false;
//
// The requested state, we need to know for each one whether it
// was ever set and for
//
SettableState _position;
SettableState _mediaState;
SettableState _source;
SettableState _clock;
SettableState _speedRatio;
SettableState _volume;
SettableState _isMuted;
SettableState _balance;
SettableState _isScrubbingEnabled;
#endregion
}
#endregion
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// File: avelementhelper.cs
//
// Description: Contains the AVElementHelper class.
//
// History:
// 05/04/2004 : [....] - Added
//
//---------------------------------------------------------------------------
using MS.Internal;
using MS.Utility;
using System.Diagnostics;
using System.Windows.Threading;
using System;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Security;
using System.Security.Permissions;
namespace System.Windows.Controls
{
#region SettableState
///
/// Settable State, keeps track of what state was set and whether it has
/// been set recently.
///
internal struct SettableState
{
internal T _value;
internal bool _isSet;
internal bool _wasSet;
internal
SettableState(
T value
)
{
_value = value;
_isSet = _wasSet = false;
}
}
#endregion
#region AVElementHelper
///
/// AVElementHelper
///
internal class AVElementHelper
{
#region Constructor
///
/// Constructor, point to the corresponding MediaElement.
///
internal AVElementHelper(MediaElement element)
{
Debug.Assert((element != null), "Element is null");
_element = element;
_position = new SettableState(new TimeSpan(0));
//
// We always start off in a closed state.
//
_mediaState = new SettableState(MediaState.Close);
_source = new SettableState(null);
_clock = new SettableState(null);
_speedRatio = new SettableState(1.0);
_volume = new SettableState(0.5);
_isMuted = new SettableState(false);
_balance = new SettableState(0.0);
_isScrubbingEnabled = new SettableState(false);
_mediaPlayer = new MediaPlayer();
HookEvents();
}
#endregion
#region Internal and Private Properties / Methods
///
/// Returns the helper class given a dependency object
///
internal static AVElementHelper GetHelper(DependencyObject d)
{
MediaElement mediaElement = d as MediaElement;
if (mediaElement != null)
{
return mediaElement.Helper;
}
else
{
throw new ArgumentException(SR.Get(SRID.AudioVideo_InvalidDependencyObject));
}
}
///
/// MediaPlayer associated with the element.
///
internal MediaPlayer Player
{
get
{
return _mediaPlayer;
}
}
///
/// Base Uri to use when resolving relative Uri's
///
internal Uri BaseUri
{
get
{
return _baseUri;
}
set
{
// ignore pack URIs for now (see work items 45396 and 41636)
if (value.Scheme != System.IO.Packaging.PackUriHelper.UriSchemePack)
{
_baseUri = value;
}
else
{
_baseUri = null;
}
}
}
///
/// Allows the behavior the Media Element should have when it is unloaded
/// to be expressed. This is a method because it can have side-effects
/// (Media could start playing or pause or perform a number of other
/// actions).
///
internal
void
SetUnloadedBehavior(
MediaState unloadedBehavior
)
{
_unloadedBehavior = unloadedBehavior;
HandleStateChange();
}
///
/// Changes the loaded behavior. This is a method because it can cause
/// side effects on other properties. (It could cause me to start or
/// stop playing, for example).
///
internal
void
SetLoadedBehavior(
MediaState loadedBehavior
)
{
_loadedBehavior = loadedBehavior;
HandleStateChange();
}
///
/// Returns the current position of the media.
///
internal TimeSpan Position
{
get
{
//
// If we have been closed, position is just a cached value,
// return it.
//
if (_currentState == MediaState.Close)
{
return _position._value;
}
else
{
return _mediaPlayer.Position;
}
}
}
///
/// Sets the current position of the media. This is a method
/// and not a property because it has side effects.
///
internal
void
SetPosition(
TimeSpan position
)
{
_position._isSet = true;
_position._value = position;
//
// If the media isn't closed, then we can actually send
// this down to the unmanaged state engine. It gets
// snippy if you try to change the position when it
// is closed.
//
HandleStateChange();
}
internal MediaClock Clock
{
get
{
return _clock._value;
}
}
internal
void
SetClock(
MediaClock clock
)
{
_clock._value = clock;
//
// We don't use _wasSet for clocks because our behavior changes dramatically
// whether _value is null or not.
//
_clock._isSet = true;
HandleStateChange();
}
internal double SpeedRatio
{
get
{
return _speedRatio._value;
}
}
internal
void
SetSpeedRatio(
double speedRatio
)
{
_speedRatio._wasSet = _speedRatio._isSet = true;
_speedRatio._value = speedRatio;
HandleStateChange();
}
internal
void
SetState(
MediaState mediaState
)
{
//
// If the caller hasn't requested any loaded or unloaded behavior to be manual
// then calls to Play/Pause/Stop etc. will never take effect.
//
if (_loadedBehavior != MediaState.Manual && _unloadedBehavior != MediaState.Manual)
{
throw new NotSupportedException(SR.Get(SRID.AudioVideo_CannotControlMedia));
}
_mediaState._value = mediaState;
_mediaState._isSet = true;
HandleStateChange();
}
internal
void
SetVolume(
double volume
)
{
_volume._wasSet = _volume._isSet = true;
_volume._value = volume;
HandleStateChange();
}
internal
void
SetBalance(
double balance
)
{
_balance._wasSet = _balance._isSet = true;
_balance._value = balance;
HandleStateChange();
}
internal
void
SetIsMuted(
bool isMuted
)
{
_isMuted._wasSet = _isMuted._isSet = true;
_isMuted._value = isMuted;
HandleStateChange();
}
internal
void
SetScrubbingEnabled(
bool isScrubbingEnabled
)
{
_isScrubbingEnabled._wasSet = _isScrubbingEnabled._isSet = true;
_isScrubbingEnabled._value = isScrubbingEnabled;
HandleStateChange();
}
///
/// Hook Events when clock is created/changed
///
private void HookEvents()
{
// register the new clock events
_mediaPlayer.MediaOpened += new EventHandler(OnMediaOpened);
_mediaPlayer.MediaFailed += new EventHandler(OnMediaFailed);
_mediaPlayer.BufferingStarted += new EventHandler(OnBufferingStarted);
_mediaPlayer.BufferingEnded += new EventHandler(OnBufferingEnded);
_mediaPlayer.MediaEnded += new EventHandler(OnMediaEnded);
_mediaPlayer.ScriptCommand += new EventHandler(OnScriptCommand);
_element.Loaded += new RoutedEventHandler(this.OnLoaded);
_element.Unloaded += new RoutedEventHandler(this.OnUnloaded);
}
///
/// All state changes to the media element come through this code, we first
/// look at all of the media element properties and the loaded behavior and
/// source property to see whether to open or close the media, the we set
/// other properties that actually control media and have been cached up.
///
private
void
HandleStateChange(
)
{
//
// First, just assume that our requested actions are going to be
// the same as the media requested actions.
//
MediaState thisStateRequest = _mediaState._value;
bool openClock = false;
bool actionRequested = false;
//
// If the element is loaded
//
if (_isLoaded)
{
//
// If we have a clock, then our loaded behavior is always manual.
// The clock always wins.
//
if (_clock._value != null)
{
thisStateRequest = MediaState.Manual;
openClock = true;
}
//
// If the loaded behavior was set, it wins over whether the
// source was set or not.
//
else if (_loadedBehavior != MediaState.Manual)
{
//
// If it is manual, it doesn't override the requested state.
//
thisStateRequest = _loadedBehavior;
}
else if (_source._wasSet)
{
if (_loadedBehavior != MediaState.Manual)
{
thisStateRequest = MediaState.Play;
}
else
{
actionRequested = true;
}
}
}
else
{
//
// If the unloaded behavior is manual, it doesn't override the
// requested state,
//
if (_unloadedBehavior != MediaState.Manual)
{
thisStateRequest = _unloadedBehavior;
}
else
{
//
// For situations in which we don't received loaded and unloaded
// events, (like VisualBrush), we need to set our UnloadedBehavior
// to Manual in order to allow storyboards to be able to control
// the media element.
//
Invariant.Assert(_unloadedBehavior == MediaState.Manual);
if (_clock._value != null)
{
thisStateRequest = MediaState.Manual;
openClock = true;
}
//
// Otherwise, an action was requested, we need to take it.
//
else
{
actionRequested = true;
}
}
}
bool openedMedia = false;
//
// If the media state is anything other than close
// and the current state is closed, the media needs to be opened.
//
if ( thisStateRequest != MediaState.Close
&& thisStateRequest != MediaState.Manual)
{
//
// We shouldn't have a clock to open because this would have a state
// request of MediaState.Manual.
//
Invariant.Assert(openClock == false);
//
// If we had a clock, get rid of it now. This is to handle the case
// where UnloadedBehavior is specified after the timing engine has
// been in control.
//
if (_mediaPlayer.Clock != null)
{
_mediaPlayer.Clock = null;
}
//
// If we are currently closed, we should open. If the source property
// was assigned, we should also open.
//
if (_currentState == MediaState.Close || _source._isSet)
{
//
// ScrubbingEnabled needs to be set before opening media in
// order to get the initial scrub.
//
if (_isScrubbingEnabled._wasSet)
{
_mediaPlayer.ScrubbingEnabled = _isScrubbingEnabled._value;
_isScrubbingEnabled._isSet = false;
}
if (_clock._value == null)
{
_mediaPlayer.Open(UriFromSourceUri(_source._value));
}
openedMedia = true;
}
}
else if (openClock)
{
//
// If either we were closed before, or if a clock was re-assigned without
// a state transition, then, re-apply the clock.
//
if (_currentState == MediaState.Close || _clock._isSet)
{
//
// ScrubbingEnabled needs to be set before opening media in
// order to get the initial scrub.
//
if (_isScrubbingEnabled._wasSet)
{
_mediaPlayer.ScrubbingEnabled = _isScrubbingEnabled._value;
_isScrubbingEnabled._isSet = false;
}
_mediaPlayer.Clock = _clock._value;
_clock._isSet = false;
openedMedia = true;
}
}
//
// Otherwise, if the request is for a Close and and we aren't in a closed state,
// we need to close.
//
else if (thisStateRequest == MediaState.Close)
{
if (_currentState != MediaState.Close)
{
//
// Dis-associate the clock from the player (if it has one).
// (Otherwise, it won't let us close it).
//
_mediaPlayer.Clock = null;
_mediaPlayer.Close();
_currentState = MediaState.Close;
}
}
//
// If we either just opened the media, or if we weren't closed in the
// first place, we get to perform all of the other actions.
//
if (_currentState != MediaState.Close || openedMedia)
{
//
// If we have a position request, do it now.
//
if (_position._isSet)
{
_mediaPlayer.Position = _position._value;
_position._isSet = false;
}
//
// Do volume state changes before a play so that we don't get either
// no sound or a loud sound on the play transition.
//
if (_volume._isSet || openedMedia && _volume._wasSet)
{
_mediaPlayer.Volume = _volume._value;
_volume._isSet = false;
}
if (_balance._isSet || openedMedia && _balance._wasSet)
{
_mediaPlayer.Balance = _balance._value;
_balance._isSet = false;
}
if (_isMuted._isSet || openedMedia && _isMuted._wasSet)
{
_mediaPlayer.IsMuted = _isMuted._value;
_isMuted._isSet = false;
}
//
// In the case that openedMedia is true, we will have already
// applied the scrubbing enabled property prior to opening the
// media. This is necessary for initial scrubbing to work
//
if (_isScrubbingEnabled._isSet)
{
_mediaPlayer.ScrubbingEnabled = _isScrubbingEnabled._value;
_isScrubbingEnabled._isSet = false;
}
//
// If we are asked to play because the source was reset,
// then, start playing the media again.
//
if (thisStateRequest == MediaState.Play && _source._isSet)
{
//
// We always want to Play() and then set the SpeedRatio to
// 1. This ensures that whwn you change the source of a
// MediaElement via databinding, we start playing the
// media again.
//
_mediaPlayer.Play();
if (!_speedRatio._wasSet)
{
_mediaPlayer.SpeedRatio = 1;
}
//
// We have effectively `swallowed the "Play" request, if this is
// what finally brought us into this code path.
//
_source._isSet = false;
_mediaState._isSet = false;
}
//
// Might be missing out on a Play, Pause, or a stop.
// If the source is changed, we always want to do the
// requested action. Also, we want to mirror each call
// to Play, Pause and Stop down to the underlying player.
//
else if ( _currentState != thisStateRequest
|| (actionRequested && _mediaState._isSet))
{
switch(thisStateRequest)
{
case MediaState.Play:
_mediaPlayer.Play();
break;
case MediaState.Pause:
_mediaPlayer.Pause();
break;
case MediaState.Stop:
_mediaPlayer.Stop();
break;
case MediaState.Manual:
break;
default:
Invariant.Assert(false, "Unexpected state request.");
break;
}
//
// If we did this transition because an action was requested, make sure
// we don't do it again when we come in.
//
if (actionRequested)
{
_mediaState._isSet = false;
}
}
_currentState = thisStateRequest;
//
// Finally, if the speed ratio has been set, change it.
//
if (_speedRatio._isSet || openedMedia && _speedRatio._wasSet)
{
_mediaPlayer.SpeedRatio = _speedRatio._value;
_speedRatio._isSet = false;
}
}
}
///
/// Looks at the current uri and the base uri and uses it to determine
/// whether we should normalize the uri to the base or not.
///
private
Uri
UriFromSourceUri(
Uri sourceUri
)
{
if (sourceUri != null)
{
if (sourceUri.IsAbsoluteUri)
{
return sourceUri;
}
else if (BaseUri != null)
{
return new Uri(BaseUri, sourceUri);
}
}
return sourceUri;
}
#endregion
#region Delegates
///
/// Raised when source is changed
///
///
/// Critical: This code calls into PresentationSource.CriticalFromVisual to
/// extract presentationsource.
/// TreatAsSafe: The value is not exposed and the call simply checks to see
/// if the value is null
///
[SecurityCritical,SecurityTreatAsSafe]
internal static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.IsASubPropertyChange)
{
return;
}
AVElementHelper aveh = AVElementHelper.GetHelper(d);
aveh.MemberOnInvalidateSource(e); // call non-static
}
private void MemberOnInvalidateSource(DependencyPropertyChangedEventArgs e)
{
if (_clock._value != null)
{
throw new InvalidOperationException(SR.Get(SRID.MediaElement_CannotSetSourceOnMediaElementDrivenByClock));
}
_source._value = (Uri)e.NewValue;
_source._wasSet = _source._isSet = true;
HandleStateChange();
}
///
/// Raised when there is a error with media playback
///
private
void
OnMediaFailed(
object sender,
ExceptionEventArgs args
)
{
//
// Propagate the error to the media element.
//
_element.OnMediaFailed(sender, args);
}
///
/// Raised when media is opened
///
private
void
OnMediaOpened(
object sender,
EventArgs args
)
{
// Whenever a new file is opened the size of the MediaElement may change
_element.InvalidateMeasure();
_element.OnMediaOpened(sender, args);
}
private
void
OnBufferingStarted(
object sender,
EventArgs args
)
{
_element.OnBufferingStarted(sender, args);
}
private
void
OnBufferingEnded(
object sender,
EventArgs args
)
{
_element.OnBufferingEnded(sender, args);
}
private
void
OnMediaEnded(
object sender,
EventArgs args
)
{
_element.OnMediaEnded(sender, args);
}
private
void
OnScriptCommand(
object sender,
MediaScriptCommandEventArgs args
)
{
_element.OnScriptCommand(sender, args);
}
private
void
OnLoaded(
object sender,
RoutedEventArgs args
)
{
_isLoaded = true;
HandleStateChange();
}
private
void
OnUnloaded(
object sender,
RoutedEventArgs args
)
{
_isLoaded = false;
HandleStateChange();
}
#endregion
#region Data Members
///
/// MediaPlayer
///
private MediaPlayer _mediaPlayer;
///
/// UIElement that owns this helper
///
private MediaElement _element;
private Uri _baseUri;
private MediaState _unloadedBehavior = MediaState.Close;
private MediaState _loadedBehavior = MediaState.Play;
private MediaState _currentState = MediaState.Close;
private bool _isLoaded = false;
//
// The requested state, we need to know for each one whether it
// was ever set and for
//
SettableState _position;
SettableState _mediaState;
SettableState _source;
SettableState _clock;
SettableState _speedRatio;
SettableState _volume;
SettableState _isMuted;
SettableState _balance;
SettableState _isScrubbingEnabled;
#endregion
}
#endregion
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DbProviderFactoriesConfigurationHandler.cs
- AgileSafeNativeMemoryHandle.cs
- InstanceCollisionException.cs
- EditBehavior.cs
- FontSizeConverter.cs
- XmlKeywords.cs
- HMACSHA512.cs
- FunctionParameter.cs
- ResourceProviderFactory.cs
- SafeProcessHandle.cs
- ZipIOBlockManager.cs
- XamlPathDataSerializer.cs
- ManagedWndProcTracker.cs
- XmlSchemaProviderAttribute.cs
- FrameworkPropertyMetadata.cs
- ResourceBinder.cs
- SplitterPanel.cs
- Rotation3D.cs
- SqlClientFactory.cs
- TemplateParser.cs
- HttpDebugHandler.cs
- XmlChildEnumerator.cs
- ButtonChrome.cs
- WinFormsSecurity.cs
- AccessViolationException.cs
- GridViewUpdatedEventArgs.cs
- PolicyUnit.cs
- OutputScopeManager.cs
- QuaternionConverter.cs
- ImageFormat.cs
- SEHException.cs
- ValidationError.cs
- LinkedResource.cs
- XmlSchemaObjectTable.cs
- DataGridViewCellStyleConverter.cs
- GraphicsContainer.cs
- ScrollableControlDesigner.cs
- panel.cs
- WsatStrings.cs
- ScriptControlDescriptor.cs
- PrintDialog.cs
- WebPartConnectionCollection.cs
- EmbeddedMailObjectsCollection.cs
- DrawingDrawingContext.cs
- MethodExpression.cs
- RoleGroupCollection.cs
- CodeDOMUtility.cs
- StreamGeometryContext.cs
- GeneratedCodeAttribute.cs
- DragEvent.cs
- XmlSignatureManifest.cs
- ExpressionEditorSheet.cs
- QueryContinueDragEvent.cs
- PersonalizationStateInfoCollection.cs
- SelectedPathEditor.cs
- Splitter.cs
- AutomationPropertyInfo.cs
- ResourceExpressionEditorSheet.cs
- XmlIncludeAttribute.cs
- PanelStyle.cs
- TextAutomationPeer.cs
- SQLCharsStorage.cs
- Transactions.cs
- AssemblyBuilderData.cs
- PipelineDeploymentState.cs
- LeafCellTreeNode.cs
- TreeIterator.cs
- GACMembershipCondition.cs
- XmlLanguageConverter.cs
- RotateTransform3D.cs
- NullToBooleanConverter.cs
- OuterGlowBitmapEffect.cs
- Schema.cs
- PostBackTrigger.cs
- TextElementCollectionHelper.cs
- FilterQuery.cs
- ImageFormat.cs
- ProxyFragment.cs
- NetworkStream.cs
- HttpCookieCollection.cs
- PointCollection.cs
- SatelliteContractVersionAttribute.cs
- BitmapCodecInfoInternal.cs
- DataSetSchema.cs
- XPathDescendantIterator.cs
- ValidationEventArgs.cs
- RegionData.cs
- _NTAuthentication.cs
- FontFaceLayoutInfo.cs
- OpenTypeLayoutCache.cs
- ObjectIDGenerator.cs
- ExpressionNormalizer.cs
- FunctionDescription.cs
- FunctionMappingTranslator.cs
- PassportAuthenticationEventArgs.cs
- ContentDisposition.cs
- PriorityQueue.cs
- SetIndexBinder.cs
- WmlLiteralTextAdapter.cs
- XomlCompilerHelpers.cs