Urgent issue with the MediaEnded event

Mar 18, 2010 at 7:22 AM

Im trying to create a situation where I have 3 videos and I want to play each one after succession randomly.

i.e. play video 0, video 2, video 1 then play video 1, video 0, video 2

I have a MediaEnded events on each of the MediaUriElement objects, and I have it so that they know which ones to play next, this work for the first time through only

After I try to play the 2nd "set", the MediaEnded event does not fire at all...

What could cause the media element to either, lose the event callback OR not call the event callback?

This is very urgent as tomorrow is the dead line and this should be trivial for me, but I just cannot for the life of me figure out what is wrong

I have each of the 3 videos defined like so:

<WPFMediaKit_DirectShow_Controls:MediaUriElement Height="705" Width="848.473" RenderTransformOrigin="0.5,0.5" Source="Movies/intro_ld4200.mpg" UnloadedBehavior="Manual" LoadedBehavior="Manual" Canvas.Left="272"/>

<WPFMediaKit_DirectShow_Controls:MediaUriElement Height="570" Width="686" RenderTransformOrigin="0.5,0.5" Source="Movies/intro_ld4200tm.mpg" UnloadedBehavior="Manual" LoadedBehavior="Manual" Canvas.Left="350" Canvas.Top="62"/>

<WPFMediaKit_DirectShow_Controls:MediaUriElement Height="570" Width="686" RenderTransformOrigin="0.5,0.5" UnloadedBehavior="Manual" LoadedBehavior="Manual" Canvas.Left="350" Canvas.Top="62" Source="Movies/intro_ld4700.mpg"/>

 

I have tried different unloading behaviors, Ive tried not stopping the media but pausing it then setting its position back to zero, ive tried physically re-adding the MediaEnded event to each of the videos with no luck at all.

Please help,

Thanks

Mark

Aug 9, 2010 at 9:43 PM
I am also experiencing this issue. Did you ever figure it out?
Aug 9, 2010 at 10:56 PM

Actually I think I did, I ended up using the standard MediaElement control instead of the MediaUriElement...

 

Here is the class I made for it, I think youll get the idea:

 

class VideoRandomiser
    {
        private class VideoPlayChain
        {
            public int? NextVideoToPlay;
            public ProductDetailControl ProductControl;
        }

        private VideoPlayChain Video1 { get; set; }
        private VideoPlayChain Video2 { get; set; }
        private VideoPlayChain Video3 { get; set; }

        private VideoPlayChain[] _videos;
        private readonly Random _random = new Random(DateTime.Now.Millisecond);
        private int _last = -1;

        private VideoPlayChain[] Videos
        {
            get { return _videos ?? (_videos = new[] {Video1, Video2, Video3}); }
        }

        private VideoPlayChain GetFromVideo(MediaElement video)
        {
            return Videos.FirstOrDefault(v => v.ProductControl.GetVideo() == video);
        }

        public VideoRandomiser(ProductDetailControl pdc1, ProductDetailControl pdc2, ProductDetailControl pdc3)
        {
            Video1 = new VideoPlayChain { ProductControl = pdc1 };
            Video2 = new VideoPlayChain { ProductControl = pdc2 };
            Video3 = new VideoPlayChain { ProductControl = pdc3 };
        }

        public void StartRandomisation()
        {
            var availableNumbers = new List<int> {0, 1, 2};
            var set = new int[3];

            //null out the video NextVideoToPlay indexes
            CleanVideoPlayChains();

            //setup the initial callbacks to play next video
            foreach (var vpc in Videos)
            {
                vpc.ProductControl.GetVideo().MediaEnded += Video_MediaEnded;
            }

            //choose a random "set"
            for (var i = 0; i < 3; i++)
            {
                var index = _random.Next(0, availableNumbers.Count);
                var num = availableNumbers[index];

                while (num == _last && i == 0)
                {
                    index = _random.Next(0, availableNumbers.Count);
                    num = availableNumbers[index];
                }

                set[i] = num;
                
                if (i != 0)
                    _videos[set[i-1]].NextVideoToPlay = num;

                availableNumbers.Remove(num);
            }

            _last = set[2];
            //play though the videos one by one
            PlayVideo(set[0]);
        }

        private void CleanVideoPlayChains()
        {
            foreach (var vpc in Videos)
            {
                vpc.NextVideoToPlay = null;
                vpc.ProductControl.GetVideo().MediaEnded -= Video_MediaEnded;
            }
        }

        void Video_MediaEnded(object sender, RoutedEventArgs e)
        {
            var videoPlayChain = GetFromVideo((MediaElement)sender);

            foreach (var p in Videos)
            {
                p.ProductControl.StopVideo();
            }

            if (videoPlayChain.NextVideoToPlay != null)
                PlayVideo(videoPlayChain.NextVideoToPlay.Value);
            else
                StartRandomisation();
        }

        private void PlayVideo(int indexToPlay)
        {
            Videos[indexToPlay].ProductControl.PlayVideo();
        }

        public void StopVideos()
        {
            foreach (var videoPlayChain in Videos)
            {
                videoPlayChain.ProductControl.StopVideo();
            }
        }
    }

Cheers,

Mark

Apr 4, 2013 at 12:16 AM
I think a solution might be to set a MediaMarker at the MediaOpened event (can't set one before that event) and use the MediaElement.NaturalDuration there to specify that the marker is at the end. When you get the MarkerReached event for that specific marker you can stop the mediaelement by code