MediaElement.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / Controls / MediaElement.cs / 1 / MediaElement.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
// File: MediaElement.cs 
//
// Description: Contains the MediaElement class. 
// 
// History:
//  07/28/2003 : [....]  - Added 
//
//---------------------------------------------------------------------------

using MS.Internal; 
using MS.Utility;
using System; 
using System.ComponentModel; 
using System.Diagnostics;
using System.Windows.Automation.Peers; 
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading; 
using System.Windows.Markup;
 
namespace System.Windows.Controls 
{
    ///  
    /// States that can be applied to the media element automatically when the
    /// MediaElement is loaded or unloaded.
    /// 
    public enum MediaState : int 
    {
        ///  
        /// The media element should be controlled manually, either by its associated 
        /// clock, or by directly calling the Play/Pause etc. on the media element.
        ///  
        Manual = 0,

        /// 
        /// The media element should play. 
        /// 
        Play = 1, 
 
        /// 
        /// The media element should close. This stops all media processing and releases 
        /// any video memory held by the media element.
        /// 
        Close = 2,
 
        /// 
        /// The media element should pause. 
        ///  
        Pause = 3,
 
        /// 
        /// The media element should stop.
        /// 
        Stop = 4 
    }
 
    ///  
    /// Media Element
    ///  
    [Localizability(LocalizationCategory.NeverLocalize)]
    public class MediaElement : FrameworkElement, IUriContext
    {
        #region Constructors 

        ///  
        /// Default DependencyObject constructor 
        /// 
        ///  
        /// Automatic determination of current Dispatcher. Use alternative constructor
        /// that accepts a Dispatcher for best performance.
        /// 
        public MediaElement() : base() 
        {
            Initialize(); 
        } 

        static MediaElement() 
        {
            Style style = CreateDefaultStyles();
            StyleProperty.OverrideMetadata(typeof(MediaElement), new FrameworkPropertyMetadata(style));
 
            //
            // The Stretch & StretchDirection properties are AddOwner'ed from a class which is not 
            // base class for MediaElement so the metadata with flags get lost. We need to override them 
            // here to make it work again.
            // 
            StretchProperty.OverrideMetadata(
                typeof(MediaElement),
                new FrameworkPropertyMetadata(
                    Stretch.Uniform, 
                    FrameworkPropertyMetadataOptions.AffectsMeasure
                    ) 
                ); 

            StretchDirectionProperty.OverrideMetadata( 
                typeof(MediaElement),
                new FrameworkPropertyMetadata(
                    StretchDirection.Both,
                    FrameworkPropertyMetadataOptions.AffectsMeasure 
                    )
                ); 
        } 

        private static Style CreateDefaultStyles() 
        {
            Style style = new Style(typeof(MediaElement), null);
            style.Setters.Add (new Setter(FlowDirectionProperty, FlowDirection.LeftToRight));
            style.Seal(); 
            return style;
        } 
 
        #endregion
 
        #region Public Properties

        /// 
        /// DependencyProperty for MediaElement Source property. 
        /// 
        ///  
        /// This property is cached (_source). 
        public static readonly DependencyProperty SourceProperty =
                DependencyProperty.Register( 
                        "Source",
                        typeof(Uri),
                        typeof(MediaElement),
                        new FrameworkPropertyMetadata( 
                                null,
                                FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, 
                                new PropertyChangedCallback(AVElementHelper.OnSourceChanged))); 

        ///  
        ///     The DependencyProperty for the MediaElement.Volume property.
        /// 
        public static readonly DependencyProperty VolumeProperty
            = DependencyProperty.Register( 
                        "Volume",
                        typeof(double), 
                        typeof(MediaElement), 
                        new FrameworkPropertyMetadata(
                              0.5, 
                              FrameworkPropertyMetadataOptions.None,
                              new PropertyChangedCallback(VolumePropertyChanged)));
        /// 
        ///     The DependencyProperty for the MediaElement.Balance property. 
        /// 
        public static readonly DependencyProperty BalanceProperty 
            = DependencyProperty.Register( 
                        "Balance",
                        typeof(double), 
                        typeof(MediaElement),
                        new FrameworkPropertyMetadata(
                              0.0,
                              FrameworkPropertyMetadataOptions.None, 
                              new PropertyChangedCallback(BalancePropertyChanged)));
 
        ///  
        /// The DependencyProperty for the MediaElement.IsMuted property.
        ///  
        public static readonly DependencyProperty IsMutedProperty
            = DependencyProperty.Register(
                        "IsMuted",
                        typeof(bool), 
                        typeof(MediaElement),
                        new FrameworkPropertyMetadata( 
                            false, 
                            FrameworkPropertyMetadataOptions.None,
                            new PropertyChangedCallback(IsMutedPropertyChanged))); 

        /// 
        /// The DependencyProperty for the MediaElement.ScrubbingEnabled property.
        ///  
        public static readonly DependencyProperty ScrubbingEnabledProperty
            = DependencyProperty.Register( 
                        "ScrubbingEnabled", 
                        typeof(bool),
                        typeof(MediaElement), 
                        new FrameworkPropertyMetadata(
                            false,
                            FrameworkPropertyMetadataOptions.None,
                            new PropertyChangedCallback(ScrubbingEnabledPropertyChanged))); 

        ///  
        /// The DependencyProperty for the MediaElement.UnloadedBehavior property. 
        /// 
        public static readonly DependencyProperty UnloadedBehaviorProperty 
            = DependencyProperty.Register(
                        "UnloadedBehavior",
                        typeof(MediaState),
                        typeof(MediaElement), 
                        new FrameworkPropertyMetadata(
                            MediaState.Close, 
                            FrameworkPropertyMetadataOptions.None, 
                            new PropertyChangedCallback(UnloadedBehaviorPropertyChanged)));
 
        /// 
        /// The DependencyProperty for the MediaElement.LoadedBehavior property.
        /// 
        public static readonly DependencyProperty LoadedBehaviorProperty 
            = DependencyProperty.Register(
                        "LoadedBehavior", 
                        typeof(MediaState), 
                        typeof(MediaElement),
                        new FrameworkPropertyMetadata( 
                            MediaState.Play,
                            FrameworkPropertyMetadataOptions.None,
                            new PropertyChangedCallback(LoadedBehaviorPropertyChanged)));
 
        /// 
        /// Gets/Sets the Source on this MediaElement. 
        /// 
        /// The Source property is the Uri of the media to be played.
        ///  
        public Uri Source
        {
            get { return (Uri)GetValue(SourceProperty); }
 
            set { SetValue(SourceProperty, value); }
        } 
 
        /// 
        /// Media Clock associated with this MediaElement. 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public MediaClock Clock
        { 
            get
            { 
                return _helper.Clock; 
            }
            set 
            {
                _helper.SetClock(value);
            }
        } 

        ///  
        /// Requests the the media is played. This method only has an effect if the current 
        /// media element state is manual.
        ///  
        public
        void
        Play()
        { 
            _helper.SetState(MediaState.Play);
        } 
 
        /// 
        /// Requests the the media is paused. This method only has an effect if the current 
        /// media element state is manual.
        /// 
        public
        void 
        Pause()
        { 
            _helper.SetState(MediaState.Pause); 
        }
 
        /// 
        /// Requests the the media is stopped. This method only has an effect if the current
        /// media element state is manual.
        ///  
        public
        void 
        Stop() 
        {
            _helper.SetState(MediaState.Stop); 
        }

        /// 
        /// Requests the the media is Closed. This method only has an effect if the current 
        /// media element state is manual.
        ///  
        public 
        void
        Close() 
        {
            _helper.SetState(MediaState.Close);
        }
 
        /// 
        /// DependencyProperty for Stretch property. 
        ///  
        /// 
        /// This property is cached and grouped (AspectRatioGroup) 
        public static readonly DependencyProperty StretchProperty =
                Viewbox.StretchProperty.AddOwner(typeof(MediaElement));

        ///  
        /// DependencyProperty for StretchDirection property.
        ///  
        ///  
        public static readonly DependencyProperty StretchDirectionProperty =
                Viewbox.StretchDirectionProperty.AddOwner(typeof(MediaElement)); 

        /// 
        /// Gets/Sets the Stretch on this MediaElement.
        /// The Stretch property determines how large the MediaElement will be drawn. 
        /// 
        ///  
        public Stretch Stretch 
        {
            get { return (Stretch) GetValue(StretchProperty); } 
            set { SetValue(StretchProperty, value); }
        }

        ///  
        /// Gets/Sets the stretch direction of the Viewbox, which determines the restrictions on
        /// scaling that are applied to the content inside the Viewbox.  For instance, this property 
        /// can be used to prevent the content from being smaller than its native size or larger than 
        /// its native size.
        ///  
        /// 
        public StretchDirection StretchDirection
        {
            get { return (StretchDirection) GetValue(StretchDirectionProperty); } 
            set { SetValue(StretchDirectionProperty, value); }
        } 
 
        /// 
        /// Gets/Sets the Volume property on the MediaElement. 
        /// 
        public double Volume
        {
            get 
            {
                return (double) GetValue(VolumeProperty); 
            } 
            set
            { 
                SetValue(VolumeProperty, value);
            }
        }
 
        /// 
        /// Gets/Sets the Balance property on the MediaElement. 
        ///  
        public double Balance
        { 
            get
            {
                return (double) GetValue(BalanceProperty);
            } 
            set
            { 
                SetValue(BalanceProperty, value); 
            }
        } 

        /// 
        /// Gets/Sets the IsMuted property on the MediaElement.
        ///  
        public bool IsMuted
        { 
            get 
            {
                return (bool) GetValue(IsMutedProperty); 
            }
            set
            {
                SetValue(IsMutedProperty, value); 
            }
        } 
 
        /// 
        /// Gets/Sets the ScrubbingEnabled property on the MediaElement. 
        /// 
        public bool ScrubbingEnabled
        {
            get 
            {
                return (bool) GetValue(ScrubbingEnabledProperty); 
            } 
            set
            { 
                SetValue(ScrubbingEnabledProperty, value);
            }
        }
 
        /// 
        /// Specifies how the underlying media should behave when the given 
        /// MediaElement is unloaded, the default behavior is to Close the 
        /// media.
        ///  
        public MediaState UnloadedBehavior
        {
            get
            { 
                return (MediaState)GetValue(UnloadedBehaviorProperty);
            } 
 
            set
            { 
                SetValue(UnloadedBehaviorProperty, value);
            }
        }
 
        /// 
        /// Specifies the behavior that the media element should have when it 
        /// is loaded. The default behavior is that it is under manual control 
        /// (i.e. the caller should call methods such as Play in order to play
        /// the media). If a source is set, then the default behavior changes to 
        /// to be playing the media. If a source is set and a loaded behavior is
        /// also set, then the loaded behavior takes control.
        /// 
        public MediaState LoadedBehavior 
        {
            get 
            { 
                return (MediaState)GetValue(LoadedBehaviorProperty);
            } 

            set
            {
                SetValue(LoadedBehaviorProperty, value); 
            }
        } 
 
        /// 
        /// Returns whether the given media can be paused. This is only valid 
        /// after the MediaOpened event has fired.
        /// 
        public bool CanPause
        { 
            get
            { 
                return _helper.Player.CanPause; 
            }
        } 

        /// 
        /// Returns whether the given media is currently being buffered. This
        /// applies to network accessed media only. 
        /// 
        public bool IsBuffering 
        { 
            get
            { 
                return _helper.Player.IsBuffering;
            }
        }
 
        /// 
        /// Returns the download progress of the media. 
        ///  
        public double DownloadProgress
        { 
            get
            {
                return _helper.Player.DownloadProgress;
            } 
        }
 
        ///  
        /// Returns the buffering progress of the media.
        ///  
        public double BufferingProgress
        {
            get
            { 
                return _helper.Player.BufferingProgress;
            } 
        } 

        ///  
        /// Returns the natural height of the media in the video. Only valid after
        /// the MediaOpened event has fired.
        /// 
        public Int32 NaturalVideoHeight 
        {
            get 
            { 
                return _helper.Player.NaturalVideoHeight;
            } 
        }

        /// 
        /// Returns the natural width of the media in the video. Only valid after 
        /// the MediaOpened event has fired.
        ///  
        public Int32 NaturalVideoWidth 
        {
            get 
            {
                return _helper.Player.NaturalVideoWidth;
            }
        } 

        ///  
        /// Returns whether the given media has audio. Only valid after the 
        /// MediaOpened event has fired.
        ///  
        public bool HasAudio
        {
            get
            { 
                return _helper.Player.HasAudio;
            } 
        } 

        ///  
        /// Returns whether the given media has video. Only valid after the
        /// MediaOpened event has fired.
        /// 
        public bool HasVideo 
        {
            get 
            { 
                return _helper.Player.HasVideo;
            } 
        }

        /// 
        /// Returns the natural duration of the media. Only valid after the 
        /// MediaOpened event has fired.
        ///  
        public Duration NaturalDuration 
        {
            get 
            {
                return _helper.Player.NaturalDuration;
            }
        } 

        ///  
        /// Returns the current position of the media. This is only valid 
        /// adter the MediaOpened event has fired.
        ///  
        public TimeSpan Position
        {
            get
            { 
                return _helper.Position;
            } 
 
            set
            { 
                _helper.SetPosition(value);
            }
        }
 
        /// 
        /// Allows the speed ration of the media to be controlled. 
        ///  
        public double SpeedRatio
        { 
            get
            {
                return _helper.SpeedRatio;
            } 

            set 
            { 
                _helper.SetSpeedRatio(value);
            } 
        }

        /// 
        /// MediaFailedEvent is a routed event. 
        /// 
        public static readonly RoutedEvent MediaFailedEvent = 
            EventManager.RegisterRoutedEvent( 
                            "MediaFailed",
                            RoutingStrategy.Bubble, 
                            typeof(EventHandler),
                            typeof(MediaElement));
        /// 
        /// Raised when there is a failure in media. 
        /// 
        public event EventHandler MediaFailed 
        { 
            add { AddHandler(MediaFailedEvent, value); }
            remove { RemoveHandler(MediaFailedEvent, value); } 
        }


        ///  
        /// MediaOpened is a routed event.
        ///  
        public static readonly RoutedEvent MediaOpenedEvent = 
            EventManager.RegisterRoutedEvent(
                            "MediaOpened", 
                            RoutingStrategy.Bubble,
                            typeof(RoutedEventHandler),
                            typeof(MediaElement));
 
        /// 
        /// Raised when the media is opened 
        ///  
        public event RoutedEventHandler MediaOpened
        { 
            add { AddHandler(MediaOpenedEvent, value);  }
            remove { RemoveHandler(MediaOpenedEvent, value); }
        }
 
        /// 
        /// BufferingStarted is a routed event. 
        ///  
        public static readonly RoutedEvent BufferingStartedEvent =
            EventManager.RegisterRoutedEvent( 
                            "BufferingStarted",
                            RoutingStrategy.Bubble,
                            typeof(RoutedEventHandler),
                            typeof(MediaElement)); 

        ///  
        /// Raised when buffering starts on the corresponding media. 
        /// 
        public event RoutedEventHandler BufferingStarted 
        {
            add { AddHandler(BufferingStartedEvent, value); }
            remove { RemoveHandler(BufferingStartedEvent, value); }
        } 

        ///  
        /// BufferingEnded is a routed event. 
        /// 
        public static readonly RoutedEvent BufferingEndedEvent = 
            EventManager.RegisterRoutedEvent(
                            "BufferingEnded",
                            RoutingStrategy.Bubble,
                            typeof(RoutedEventHandler), 
                            typeof(MediaElement));
 
        ///  
        /// Raised when buffering ends on the corresponding media.
        ///  
        public event RoutedEventHandler BufferingEnded
        {
            add { AddHandler(BufferingEndedEvent, value); }
            remove { RemoveHandler(BufferingEndedEvent, value); } 
        }
 
        ///  
        /// ScriptCommand is a routed event.
        ///  
        public static readonly RoutedEvent ScriptCommandEvent =
            EventManager.RegisterRoutedEvent(
                            "ScriptCommand",
                            RoutingStrategy.Bubble, 
                            typeof(EventHandler),
                            typeof(MediaElement)); 
 
        /// 
        /// Raised when a script command in the media is encountered during playback. 
        /// 
        public event EventHandler ScriptCommand
        {
            add { AddHandler(ScriptCommandEvent, value); } 
            remove { RemoveHandler(ScriptCommandEvent, value); }
        } 
 
        /// 
        /// MediaEnded is a routed event 
        /// 
        public static readonly RoutedEvent MediaEndedEvent =
            EventManager.RegisterRoutedEvent(
                            "MediaEnded", 
                            RoutingStrategy.Bubble,
                            typeof(RoutedEventHandler), 
                            typeof(MediaElement)); 

        ///  
        /// Raised when the corresponding media ends.
        /// 
        public event RoutedEventHandler MediaEnded
        { 
            add { AddHandler(MediaEndedEvent, value); }
            remove { RemoveHandler(MediaEndedEvent, value); } 
        } 

        #endregion 

        #region IUriContext implementation
        /// 
        /// Base Uri to use when resolving relative Uri's 
        /// 
        Uri IUriContext.BaseUri 
        { 
            get
            { 
                return _helper.BaseUri;
            }
            set
            { 
                _helper.BaseUri = value;
            } 
        } 
        #endregion
 
        #region Protected Methods

        /// 
        /// Creates AutomationPeer () 
        /// 
        protected override AutomationPeer OnCreateAutomationPeer() 
        { 
            return new MediaElementAutomationPeer(this);
        } 

        /// 
        /// Override for .
        ///  
        protected override Size MeasureOverride(Size availableSize)
        { 
            return MeasureArrangeHelper(availableSize); 
        }
 
        /// 
        /// Override for .
        /// 
        protected override Size ArrangeOverride(Size finalSize) 
        {
            return MeasureArrangeHelper(finalSize); 
        } 

        // 
        // protected override void OnArrange(Size arrangeSize)
        // Because MediaElement does not have children and it is inexpensive to compute it's alignment/size,
        // it does not need an OnArrange override.  It will simply use its own RenderSize (set when its
        // Arrange is called) in OnRender. 
        //
 
        ///  
        /// OnRender is called when the Visual is notified that its contents need to be rendered
        /// This lets the MediaElement element know that it needs to render its contents in the given 
        /// DrawingContext
        /// 
        /// 
        /// The DrawingContext to render the video to 
        /// 
        protected override void OnRender(DrawingContext drawingContext) 
        { 
            // if nobody set a source on us, then the clock will be null, so we don't render
            // anything 
            if (_helper.Player == null)
            {
                return;
            } 

            drawingContext.DrawVideo(_helper.Player, new Rect(new Point(), RenderSize)); 
 
            return;
        } 

        #endregion Protected Methods

        #region Internal Properties / Methods 

        ///  
        /// Return the helper object. 
        /// 
        internal AVElementHelper Helper 
        {
            get
            {
                return _helper; 
            }
        } 
 
        #endregion
 
        #region Private Methods

        /// 
        /// Initialization 
        /// 
        private void Initialize() 
        { 
            _helper = new AVElementHelper(this);
        } 

        /// 
        /// Contains the code common for MeasureOverride and ArrangeOverride.
        ///  
        /// input size is the parent-provided space that Video should use to "fit in", according to other properties.
        /// MediaElement's desired size. 
        private Size MeasureArrangeHelper(Size inputSize) 
        {
            MediaPlayer mediaPlayer = _helper.Player; 

            if (mediaPlayer == null)
            {
                return new Size(); 
            }
 
            Size naturalSize = new Size((double)mediaPlayer.NaturalVideoWidth, (double)mediaPlayer.NaturalVideoHeight); 

            //get computed scale factor 
            Size scaleFactor = Viewbox.ComputeScaleFactor(inputSize,
                                                          naturalSize,
                                                          this.Stretch,
                                                          this.StretchDirection); 

            // Returns our minimum size & sets DesiredSize. 
            return new Size(naturalSize.Width * scaleFactor.Width, naturalSize.Height * scaleFactor.Height); 
        }
 
        private static void VolumePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.IsASubPropertyChange)
            { 
                return;
            } 
 
            MediaElement target = ((MediaElement) d);
 
            if (target != null)
            {
                target._helper.SetVolume((double)e.NewValue);
            } 
        }
 
        private static void BalancePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            if (e.IsASubPropertyChange) 
            {
                return;
            }
 
            MediaElement target = ((MediaElement) d);
 
            if (target != null) 
            {
                target._helper.SetBalance((double)e.NewValue); 
            }
        }

        private static void IsMutedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            if (e.IsASubPropertyChange) 
            { 
                return;
            } 

            MediaElement target = ((MediaElement) d);

            if (target != null) 
            {
                target._helper.SetIsMuted((bool)e.NewValue); 
            } 
        }
 
        private static void ScrubbingEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.IsASubPropertyChange)
            { 
                return;
            } 
 
            MediaElement target = ((MediaElement) d);
 
            if (target != null)
            {
                target._helper.SetScrubbingEnabled((bool)e.NewValue);
            } 
        }
 
        private static 
        void
        UnloadedBehaviorPropertyChanged( 
            DependencyObject d,
            DependencyPropertyChangedEventArgs e
            )
        { 
            if (e.IsASubPropertyChange)
            { 
                return; 
            }
 
            MediaElement target = (MediaElement)d;

            if (target != null)
            { 
                target._helper.SetUnloadedBehavior((MediaState)e.NewValue);
            } 
        } 

        private static 
        void
        LoadedBehaviorPropertyChanged(
            DependencyObject d,
            DependencyPropertyChangedEventArgs e 
            )
        { 
            if (e.IsASubPropertyChange) 
            {
                return; 
            }

            MediaElement target = (MediaElement)d;
 
            if (target != null)
            { 
                target._helper.SetLoadedBehavior((MediaState)e.NewValue); 
            }
        } 

        internal
        void
        OnMediaFailed( 
            object sender,
            ExceptionEventArgs args 
            ) 
        {
            RaiseEvent( 
                new ExceptionRoutedEventArgs(
                        MediaFailedEvent,
                        this,
                        args.ErrorException)); 
        }
 
        internal 
        void
        OnMediaOpened( 
            object sender,
            EventArgs args
            )
        { 
            RaiseEvent(new RoutedEventArgs(MediaOpenedEvent, this));
        } 
 
        internal
        void 
        OnBufferingStarted(
            object sender,
            EventArgs args
            ) 
        {
            RaiseEvent(new RoutedEventArgs(BufferingStartedEvent, this)); 
        } 

        internal 
        void
        OnBufferingEnded(
            object sender,
            EventArgs args 
            )
        { 
            RaiseEvent(new RoutedEventArgs(BufferingEndedEvent, this)); 
        }
 
        internal
        void
        OnMediaEnded(
            object sender, 
            EventArgs args
            ) 
        { 
            RaiseEvent(new RoutedEventArgs(MediaEndedEvent, this));
        } 

        internal
        void
        OnScriptCommand( 
            object  sender,
            MediaScriptCommandEventArgs args 
            ) 
        {
            RaiseEvent( 
                new MediaScriptCommandRoutedEventArgs(
                        ScriptCommandEvent,
                        this,
                        args.ParameterType, 
                        args.ParameterValue));
        } 
 
        #endregion
 

        #region Data Members

        ///  
        /// Helper object
        ///  
        private AVElementHelper _helper; 

        #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: MediaElement.cs 
//
// Description: Contains the MediaElement class. 
// 
// History:
//  07/28/2003 : [....]  - Added 
//
//---------------------------------------------------------------------------

using MS.Internal; 
using MS.Utility;
using System; 
using System.ComponentModel; 
using System.Diagnostics;
using System.Windows.Automation.Peers; 
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading; 
using System.Windows.Markup;
 
namespace System.Windows.Controls 
{
    ///  
    /// States that can be applied to the media element automatically when the
    /// MediaElement is loaded or unloaded.
    /// 
    public enum MediaState : int 
    {
        ///  
        /// The media element should be controlled manually, either by its associated 
        /// clock, or by directly calling the Play/Pause etc. on the media element.
        ///  
        Manual = 0,

        /// 
        /// The media element should play. 
        /// 
        Play = 1, 
 
        /// 
        /// The media element should close. This stops all media processing and releases 
        /// any video memory held by the media element.
        /// 
        Close = 2,
 
        /// 
        /// The media element should pause. 
        ///  
        Pause = 3,
 
        /// 
        /// The media element should stop.
        /// 
        Stop = 4 
    }
 
    ///  
    /// Media Element
    ///  
    [Localizability(LocalizationCategory.NeverLocalize)]
    public class MediaElement : FrameworkElement, IUriContext
    {
        #region Constructors 

        ///  
        /// Default DependencyObject constructor 
        /// 
        ///  
        /// Automatic determination of current Dispatcher. Use alternative constructor
        /// that accepts a Dispatcher for best performance.
        /// 
        public MediaElement() : base() 
        {
            Initialize(); 
        } 

        static MediaElement() 
        {
            Style style = CreateDefaultStyles();
            StyleProperty.OverrideMetadata(typeof(MediaElement), new FrameworkPropertyMetadata(style));
 
            //
            // The Stretch & StretchDirection properties are AddOwner'ed from a class which is not 
            // base class for MediaElement so the metadata with flags get lost. We need to override them 
            // here to make it work again.
            // 
            StretchProperty.OverrideMetadata(
                typeof(MediaElement),
                new FrameworkPropertyMetadata(
                    Stretch.Uniform, 
                    FrameworkPropertyMetadataOptions.AffectsMeasure
                    ) 
                ); 

            StretchDirectionProperty.OverrideMetadata( 
                typeof(MediaElement),
                new FrameworkPropertyMetadata(
                    StretchDirection.Both,
                    FrameworkPropertyMetadataOptions.AffectsMeasure 
                    )
                ); 
        } 

        private static Style CreateDefaultStyles() 
        {
            Style style = new Style(typeof(MediaElement), null);
            style.Setters.Add (new Setter(FlowDirectionProperty, FlowDirection.LeftToRight));
            style.Seal(); 
            return style;
        } 
 
        #endregion
 
        #region Public Properties

        /// 
        /// DependencyProperty for MediaElement Source property. 
        /// 
        ///  
        /// This property is cached (_source). 
        public static readonly DependencyProperty SourceProperty =
                DependencyProperty.Register( 
                        "Source",
                        typeof(Uri),
                        typeof(MediaElement),
                        new FrameworkPropertyMetadata( 
                                null,
                                FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, 
                                new PropertyChangedCallback(AVElementHelper.OnSourceChanged))); 

        ///  
        ///     The DependencyProperty for the MediaElement.Volume property.
        /// 
        public static readonly DependencyProperty VolumeProperty
            = DependencyProperty.Register( 
                        "Volume",
                        typeof(double), 
                        typeof(MediaElement), 
                        new FrameworkPropertyMetadata(
                              0.5, 
                              FrameworkPropertyMetadataOptions.None,
                              new PropertyChangedCallback(VolumePropertyChanged)));
        /// 
        ///     The DependencyProperty for the MediaElement.Balance property. 
        /// 
        public static readonly DependencyProperty BalanceProperty 
            = DependencyProperty.Register( 
                        "Balance",
                        typeof(double), 
                        typeof(MediaElement),
                        new FrameworkPropertyMetadata(
                              0.0,
                              FrameworkPropertyMetadataOptions.None, 
                              new PropertyChangedCallback(BalancePropertyChanged)));
 
        ///  
        /// The DependencyProperty for the MediaElement.IsMuted property.
        ///  
        public static readonly DependencyProperty IsMutedProperty
            = DependencyProperty.Register(
                        "IsMuted",
                        typeof(bool), 
                        typeof(MediaElement),
                        new FrameworkPropertyMetadata( 
                            false, 
                            FrameworkPropertyMetadataOptions.None,
                            new PropertyChangedCallback(IsMutedPropertyChanged))); 

        /// 
        /// The DependencyProperty for the MediaElement.ScrubbingEnabled property.
        ///  
        public static readonly DependencyProperty ScrubbingEnabledProperty
            = DependencyProperty.Register( 
                        "ScrubbingEnabled", 
                        typeof(bool),
                        typeof(MediaElement), 
                        new FrameworkPropertyMetadata(
                            false,
                            FrameworkPropertyMetadataOptions.None,
                            new PropertyChangedCallback(ScrubbingEnabledPropertyChanged))); 

        ///  
        /// The DependencyProperty for the MediaElement.UnloadedBehavior property. 
        /// 
        public static readonly DependencyProperty UnloadedBehaviorProperty 
            = DependencyProperty.Register(
                        "UnloadedBehavior",
                        typeof(MediaState),
                        typeof(MediaElement), 
                        new FrameworkPropertyMetadata(
                            MediaState.Close, 
                            FrameworkPropertyMetadataOptions.None, 
                            new PropertyChangedCallback(UnloadedBehaviorPropertyChanged)));
 
        /// 
        /// The DependencyProperty for the MediaElement.LoadedBehavior property.
        /// 
        public static readonly DependencyProperty LoadedBehaviorProperty 
            = DependencyProperty.Register(
                        "LoadedBehavior", 
                        typeof(MediaState), 
                        typeof(MediaElement),
                        new FrameworkPropertyMetadata( 
                            MediaState.Play,
                            FrameworkPropertyMetadataOptions.None,
                            new PropertyChangedCallback(LoadedBehaviorPropertyChanged)));
 
        /// 
        /// Gets/Sets the Source on this MediaElement. 
        /// 
        /// The Source property is the Uri of the media to be played.
        ///  
        public Uri Source
        {
            get { return (Uri)GetValue(SourceProperty); }
 
            set { SetValue(SourceProperty, value); }
        } 
 
        /// 
        /// Media Clock associated with this MediaElement. 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public MediaClock Clock
        { 
            get
            { 
                return _helper.Clock; 
            }
            set 
            {
                _helper.SetClock(value);
            }
        } 

        ///  
        /// Requests the the media is played. This method only has an effect if the current 
        /// media element state is manual.
        ///  
        public
        void
        Play()
        { 
            _helper.SetState(MediaState.Play);
        } 
 
        /// 
        /// Requests the the media is paused. This method only has an effect if the current 
        /// media element state is manual.
        /// 
        public
        void 
        Pause()
        { 
            _helper.SetState(MediaState.Pause); 
        }
 
        /// 
        /// Requests the the media is stopped. This method only has an effect if the current
        /// media element state is manual.
        ///  
        public
        void 
        Stop() 
        {
            _helper.SetState(MediaState.Stop); 
        }

        /// 
        /// Requests the the media is Closed. This method only has an effect if the current 
        /// media element state is manual.
        ///  
        public 
        void
        Close() 
        {
            _helper.SetState(MediaState.Close);
        }
 
        /// 
        /// DependencyProperty for Stretch property. 
        ///  
        /// 
        /// This property is cached and grouped (AspectRatioGroup) 
        public static readonly DependencyProperty StretchProperty =
                Viewbox.StretchProperty.AddOwner(typeof(MediaElement));

        ///  
        /// DependencyProperty for StretchDirection property.
        ///  
        ///  
        public static readonly DependencyProperty StretchDirectionProperty =
                Viewbox.StretchDirectionProperty.AddOwner(typeof(MediaElement)); 

        /// 
        /// Gets/Sets the Stretch on this MediaElement.
        /// The Stretch property determines how large the MediaElement will be drawn. 
        /// 
        ///  
        public Stretch Stretch 
        {
            get { return (Stretch) GetValue(StretchProperty); } 
            set { SetValue(StretchProperty, value); }
        }

        ///  
        /// Gets/Sets the stretch direction of the Viewbox, which determines the restrictions on
        /// scaling that are applied to the content inside the Viewbox.  For instance, this property 
        /// can be used to prevent the content from being smaller than its native size or larger than 
        /// its native size.
        ///  
        /// 
        public StretchDirection StretchDirection
        {
            get { return (StretchDirection) GetValue(StretchDirectionProperty); } 
            set { SetValue(StretchDirectionProperty, value); }
        } 
 
        /// 
        /// Gets/Sets the Volume property on the MediaElement. 
        /// 
        public double Volume
        {
            get 
            {
                return (double) GetValue(VolumeProperty); 
            } 
            set
            { 
                SetValue(VolumeProperty, value);
            }
        }
 
        /// 
        /// Gets/Sets the Balance property on the MediaElement. 
        ///  
        public double Balance
        { 
            get
            {
                return (double) GetValue(BalanceProperty);
            } 
            set
            { 
                SetValue(BalanceProperty, value); 
            }
        } 

        /// 
        /// Gets/Sets the IsMuted property on the MediaElement.
        ///  
        public bool IsMuted
        { 
            get 
            {
                return (bool) GetValue(IsMutedProperty); 
            }
            set
            {
                SetValue(IsMutedProperty, value); 
            }
        } 
 
        /// 
        /// Gets/Sets the ScrubbingEnabled property on the MediaElement. 
        /// 
        public bool ScrubbingEnabled
        {
            get 
            {
                return (bool) GetValue(ScrubbingEnabledProperty); 
            } 
            set
            { 
                SetValue(ScrubbingEnabledProperty, value);
            }
        }
 
        /// 
        /// Specifies how the underlying media should behave when the given 
        /// MediaElement is unloaded, the default behavior is to Close the 
        /// media.
        ///  
        public MediaState UnloadedBehavior
        {
            get
            { 
                return (MediaState)GetValue(UnloadedBehaviorProperty);
            } 
 
            set
            { 
                SetValue(UnloadedBehaviorProperty, value);
            }
        }
 
        /// 
        /// Specifies the behavior that the media element should have when it 
        /// is loaded. The default behavior is that it is under manual control 
        /// (i.e. the caller should call methods such as Play in order to play
        /// the media). If a source is set, then the default behavior changes to 
        /// to be playing the media. If a source is set and a loaded behavior is
        /// also set, then the loaded behavior takes control.
        /// 
        public MediaState LoadedBehavior 
        {
            get 
            { 
                return (MediaState)GetValue(LoadedBehaviorProperty);
            } 

            set
            {
                SetValue(LoadedBehaviorProperty, value); 
            }
        } 
 
        /// 
        /// Returns whether the given media can be paused. This is only valid 
        /// after the MediaOpened event has fired.
        /// 
        public bool CanPause
        { 
            get
            { 
                return _helper.Player.CanPause; 
            }
        } 

        /// 
        /// Returns whether the given media is currently being buffered. This
        /// applies to network accessed media only. 
        /// 
        public bool IsBuffering 
        { 
            get
            { 
                return _helper.Player.IsBuffering;
            }
        }
 
        /// 
        /// Returns the download progress of the media. 
        ///  
        public double DownloadProgress
        { 
            get
            {
                return _helper.Player.DownloadProgress;
            } 
        }
 
        ///  
        /// Returns the buffering progress of the media.
        ///  
        public double BufferingProgress
        {
            get
            { 
                return _helper.Player.BufferingProgress;
            } 
        } 

        ///  
        /// Returns the natural height of the media in the video. Only valid after
        /// the MediaOpened event has fired.
        /// 
        public Int32 NaturalVideoHeight 
        {
            get 
            { 
                return _helper.Player.NaturalVideoHeight;
            } 
        }

        /// 
        /// Returns the natural width of the media in the video. Only valid after 
        /// the MediaOpened event has fired.
        ///  
        public Int32 NaturalVideoWidth 
        {
            get 
            {
                return _helper.Player.NaturalVideoWidth;
            }
        } 

        ///  
        /// Returns whether the given media has audio. Only valid after the 
        /// MediaOpened event has fired.
        ///  
        public bool HasAudio
        {
            get
            { 
                return _helper.Player.HasAudio;
            } 
        } 

        ///  
        /// Returns whether the given media has video. Only valid after the
        /// MediaOpened event has fired.
        /// 
        public bool HasVideo 
        {
            get 
            { 
                return _helper.Player.HasVideo;
            } 
        }

        /// 
        /// Returns the natural duration of the media. Only valid after the 
        /// MediaOpened event has fired.
        ///  
        public Duration NaturalDuration 
        {
            get 
            {
                return _helper.Player.NaturalDuration;
            }
        } 

        ///  
        /// Returns the current position of the media. This is only valid 
        /// adter the MediaOpened event has fired.
        ///  
        public TimeSpan Position
        {
            get
            { 
                return _helper.Position;
            } 
 
            set
            { 
                _helper.SetPosition(value);
            }
        }
 
        /// 
        /// Allows the speed ration of the media to be controlled. 
        ///  
        public double SpeedRatio
        { 
            get
            {
                return _helper.SpeedRatio;
            } 

            set 
            { 
                _helper.SetSpeedRatio(value);
            } 
        }

        /// 
        /// MediaFailedEvent is a routed event. 
        /// 
        public static readonly RoutedEvent MediaFailedEvent = 
            EventManager.RegisterRoutedEvent( 
                            "MediaFailed",
                            RoutingStrategy.Bubble, 
                            typeof(EventHandler),
                            typeof(MediaElement));
        /// 
        /// Raised when there is a failure in media. 
        /// 
        public event EventHandler MediaFailed 
        { 
            add { AddHandler(MediaFailedEvent, value); }
            remove { RemoveHandler(MediaFailedEvent, value); } 
        }


        ///  
        /// MediaOpened is a routed event.
        ///  
        public static readonly RoutedEvent MediaOpenedEvent = 
            EventManager.RegisterRoutedEvent(
                            "MediaOpened", 
                            RoutingStrategy.Bubble,
                            typeof(RoutedEventHandler),
                            typeof(MediaElement));
 
        /// 
        /// Raised when the media is opened 
        ///  
        public event RoutedEventHandler MediaOpened
        { 
            add { AddHandler(MediaOpenedEvent, value);  }
            remove { RemoveHandler(MediaOpenedEvent, value); }
        }
 
        /// 
        /// BufferingStarted is a routed event. 
        ///  
        public static readonly RoutedEvent BufferingStartedEvent =
            EventManager.RegisterRoutedEvent( 
                            "BufferingStarted",
                            RoutingStrategy.Bubble,
                            typeof(RoutedEventHandler),
                            typeof(MediaElement)); 

        ///  
        /// Raised when buffering starts on the corresponding media. 
        /// 
        public event RoutedEventHandler BufferingStarted 
        {
            add { AddHandler(BufferingStartedEvent, value); }
            remove { RemoveHandler(BufferingStartedEvent, value); }
        } 

        ///  
        /// BufferingEnded is a routed event. 
        /// 
        public static readonly RoutedEvent BufferingEndedEvent = 
            EventManager.RegisterRoutedEvent(
                            "BufferingEnded",
                            RoutingStrategy.Bubble,
                            typeof(RoutedEventHandler), 
                            typeof(MediaElement));
 
        ///  
        /// Raised when buffering ends on the corresponding media.
        ///  
        public event RoutedEventHandler BufferingEnded
        {
            add { AddHandler(BufferingEndedEvent, value); }
            remove { RemoveHandler(BufferingEndedEvent, value); } 
        }
 
        ///  
        /// ScriptCommand is a routed event.
        ///  
        public static readonly RoutedEvent ScriptCommandEvent =
            EventManager.RegisterRoutedEvent(
                            "ScriptCommand",
                            RoutingStrategy.Bubble, 
                            typeof(EventHandler),
                            typeof(MediaElement)); 
 
        /// 
        /// Raised when a script command in the media is encountered during playback. 
        /// 
        public event EventHandler ScriptCommand
        {
            add { AddHandler(ScriptCommandEvent, value); } 
            remove { RemoveHandler(ScriptCommandEvent, value); }
        } 
 
        /// 
        /// MediaEnded is a routed event 
        /// 
        public static readonly RoutedEvent MediaEndedEvent =
            EventManager.RegisterRoutedEvent(
                            "MediaEnded", 
                            RoutingStrategy.Bubble,
                            typeof(RoutedEventHandler), 
                            typeof(MediaElement)); 

        ///  
        /// Raised when the corresponding media ends.
        /// 
        public event RoutedEventHandler MediaEnded
        { 
            add { AddHandler(MediaEndedEvent, value); }
            remove { RemoveHandler(MediaEndedEvent, value); } 
        } 

        #endregion 

        #region IUriContext implementation
        /// 
        /// Base Uri to use when resolving relative Uri's 
        /// 
        Uri IUriContext.BaseUri 
        { 
            get
            { 
                return _helper.BaseUri;
            }
            set
            { 
                _helper.BaseUri = value;
            } 
        } 
        #endregion
 
        #region Protected Methods

        /// 
        /// Creates AutomationPeer () 
        /// 
        protected override AutomationPeer OnCreateAutomationPeer() 
        { 
            return new MediaElementAutomationPeer(this);
        } 

        /// 
        /// Override for .
        ///  
        protected override Size MeasureOverride(Size availableSize)
        { 
            return MeasureArrangeHelper(availableSize); 
        }
 
        /// 
        /// Override for .
        /// 
        protected override Size ArrangeOverride(Size finalSize) 
        {
            return MeasureArrangeHelper(finalSize); 
        } 

        // 
        // protected override void OnArrange(Size arrangeSize)
        // Because MediaElement does not have children and it is inexpensive to compute it's alignment/size,
        // it does not need an OnArrange override.  It will simply use its own RenderSize (set when its
        // Arrange is called) in OnRender. 
        //
 
        ///  
        /// OnRender is called when the Visual is notified that its contents need to be rendered
        /// This lets the MediaElement element know that it needs to render its contents in the given 
        /// DrawingContext
        /// 
        /// 
        /// The DrawingContext to render the video to 
        /// 
        protected override void OnRender(DrawingContext drawingContext) 
        { 
            // if nobody set a source on us, then the clock will be null, so we don't render
            // anything 
            if (_helper.Player == null)
            {
                return;
            } 

            drawingContext.DrawVideo(_helper.Player, new Rect(new Point(), RenderSize)); 
 
            return;
        } 

        #endregion Protected Methods

        #region Internal Properties / Methods 

        ///  
        /// Return the helper object. 
        /// 
        internal AVElementHelper Helper 
        {
            get
            {
                return _helper; 
            }
        } 
 
        #endregion
 
        #region Private Methods

        /// 
        /// Initialization 
        /// 
        private void Initialize() 
        { 
            _helper = new AVElementHelper(this);
        } 

        /// 
        /// Contains the code common for MeasureOverride and ArrangeOverride.
        ///  
        /// input size is the parent-provided space that Video should use to "fit in", according to other properties.
        /// MediaElement's desired size. 
        private Size MeasureArrangeHelper(Size inputSize) 
        {
            MediaPlayer mediaPlayer = _helper.Player; 

            if (mediaPlayer == null)
            {
                return new Size(); 
            }
 
            Size naturalSize = new Size((double)mediaPlayer.NaturalVideoWidth, (double)mediaPlayer.NaturalVideoHeight); 

            //get computed scale factor 
            Size scaleFactor = Viewbox.ComputeScaleFactor(inputSize,
                                                          naturalSize,
                                                          this.Stretch,
                                                          this.StretchDirection); 

            // Returns our minimum size & sets DesiredSize. 
            return new Size(naturalSize.Width * scaleFactor.Width, naturalSize.Height * scaleFactor.Height); 
        }
 
        private static void VolumePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.IsASubPropertyChange)
            { 
                return;
            } 
 
            MediaElement target = ((MediaElement) d);
 
            if (target != null)
            {
                target._helper.SetVolume((double)e.NewValue);
            } 
        }
 
        private static void BalancePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            if (e.IsASubPropertyChange) 
            {
                return;
            }
 
            MediaElement target = ((MediaElement) d);
 
            if (target != null) 
            {
                target._helper.SetBalance((double)e.NewValue); 
            }
        }

        private static void IsMutedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            if (e.IsASubPropertyChange) 
            { 
                return;
            } 

            MediaElement target = ((MediaElement) d);

            if (target != null) 
            {
                target._helper.SetIsMuted((bool)e.NewValue); 
            } 
        }
 
        private static void ScrubbingEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (e.IsASubPropertyChange)
            { 
                return;
            } 
 
            MediaElement target = ((MediaElement) d);
 
            if (target != null)
            {
                target._helper.SetScrubbingEnabled((bool)e.NewValue);
            } 
        }
 
        private static 
        void
        UnloadedBehaviorPropertyChanged( 
            DependencyObject d,
            DependencyPropertyChangedEventArgs e
            )
        { 
            if (e.IsASubPropertyChange)
            { 
                return; 
            }
 
            MediaElement target = (MediaElement)d;

            if (target != null)
            { 
                target._helper.SetUnloadedBehavior((MediaState)e.NewValue);
            } 
        } 

        private static 
        void
        LoadedBehaviorPropertyChanged(
            DependencyObject d,
            DependencyPropertyChangedEventArgs e 
            )
        { 
            if (e.IsASubPropertyChange) 
            {
                return; 
            }

            MediaElement target = (MediaElement)d;
 
            if (target != null)
            { 
                target._helper.SetLoadedBehavior((MediaState)e.NewValue); 
            }
        } 

        internal
        void
        OnMediaFailed( 
            object sender,
            ExceptionEventArgs args 
            ) 
        {
            RaiseEvent( 
                new ExceptionRoutedEventArgs(
                        MediaFailedEvent,
                        this,
                        args.ErrorException)); 
        }
 
        internal 
        void
        OnMediaOpened( 
            object sender,
            EventArgs args
            )
        { 
            RaiseEvent(new RoutedEventArgs(MediaOpenedEvent, this));
        } 
 
        internal
        void 
        OnBufferingStarted(
            object sender,
            EventArgs args
            ) 
        {
            RaiseEvent(new RoutedEventArgs(BufferingStartedEvent, this)); 
        } 

        internal 
        void
        OnBufferingEnded(
            object sender,
            EventArgs args 
            )
        { 
            RaiseEvent(new RoutedEventArgs(BufferingEndedEvent, this)); 
        }
 
        internal
        void
        OnMediaEnded(
            object sender, 
            EventArgs args
            ) 
        { 
            RaiseEvent(new RoutedEventArgs(MediaEndedEvent, this));
        } 

        internal
        void
        OnScriptCommand( 
            object  sender,
            MediaScriptCommandEventArgs args 
            ) 
        {
            RaiseEvent( 
                new MediaScriptCommandRoutedEventArgs(
                        ScriptCommandEvent,
                        this,
                        args.ParameterType, 
                        args.ParameterValue));
        } 
 
        #endregion
 

        #region Data Members

        ///  
        /// Helper object
        ///  
        private AVElementHelper _helper; 

        #endregion 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK