123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- using Microsoft.WindowsAPICodePack.Shell;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Media.Animation;
- using System.Windows.Media.Imaging;
- using System.Windows.Navigation;
- using System.Windows.Shapes;
- using System.Windows.Threading;
- namespace VideoPlayer
- {
- public enum VideoState
- {
- play, stop, pause
- }
- /// <summary>
- /// WenVideoPlayer.xaml 的互動邏輯
- /// </summary>
- public partial class VideoPlayer : UserControl
- {
- public event EventHandler OnVideoComplete;
- public event EventHandler<VideoState> OnVideoStateChanged;
- /// <summary> 取得有總共有多少影片正在撥放 </summary>
- /// <return> 撥放中的數量 </return>
- public static int playingCount
- {
- get
- {
- int count = 0;
- foreach (VideoPlayer player in playerCreated)
- {
- if (player.IsPlaying)
- count++;
- }
- return count;
- }
- }
- public static void ReleaseAll()
- {
- VideoPlayer[] listClone = new VideoPlayer[playerCreated.Count];
- playerCreated.CopyTo(listClone);
- foreach (VideoPlayer player in listClone)
- {
- player.ReleaseResource();
- }
- }
- /// <summary> 阻擋對Player觸控的事件 </summary>
- public bool manipulationLocked = false;
- private static List<VideoPlayer> playerCreated = new List<VideoPlayer>();
- private MediaElement mediaSource;
- private bool stopRequest = false;
- private bool progressSliderChanging = false;
- private DispatcherTimer toolbarHideTimer = new DispatcherTimer();
- private const int timerInterval = 3000; //隱藏工具時間
- private string _videoPath;
- private MediaTimeline mt;
- private bool mediaLoadComplete = false;
- private VideoState beginBehavier;
- private double videoRatio = 0;
- private Size videoSize = new Size();
- private VideoState currentVideoState;
- private double videoLength;
- public double VideoLength
- {
- get
- {
- return videoLength;
- }
- }
- public bool IsPlaying
- {
- get
- {
- return !(mediaSource.Clock.IsPaused || mediaSource.Clock.CurrentState == ClockState.Stopped);
- }
- }
- public Size VideoSize
- {
- get
- {
- return videoSize;
- }
- }
- public string VideoPath
- {
- get
- {
- return _videoPath;
- }
- }
- public void Stop()
- {
- stop_TouchDown(null, null);
- }
- public void Play()
- {
- uxPlayButton_TouchUp(null, null);
- }
- public void Pause()
- {
- pause_TouchDown(null, null);
- }
- public void IncereaseVolume(double volume = 1)
- {
- setVolume(uxVolumeSlider.Value + volume);
- }
- public void DecressVolume(double volume = 1)
- {
- setVolume(uxVolumeSlider.Value - volume);
- }
- public void SetVolume(double volume = 1)
- {
- setVolume(volume);
- }
- public void UpdateScale(double scale)
- {
- double ratio = 1;
- ((ScaleTransform)uxControlPanel.RenderTransform).ScaleY = 1 / (scale);
- uxControlPanel.ColumnDefinitions[1].Width = new GridLength(30 / (scale * ratio), GridUnitType.Pixel);
- uxControlPanel.ColumnDefinitions[3].Width = new GridLength(30 / (scale * ratio), GridUnitType.Pixel);
- uxControlPanel.ColumnDefinitions[7].Width = new GridLength(30 / (scale * ratio), GridUnitType.Pixel);
- uxControlPanel.ColumnDefinitions[0].Width = new GridLength(15 / (scale * ratio), GridUnitType.Pixel);
- uxControlPanel.ColumnDefinitions[2].Width = new GridLength(15 / (scale * ratio), GridUnitType.Pixel);
- uxControlPanel.ColumnDefinitions[4].Width = new GridLength(15 / (scale * ratio), GridUnitType.Pixel);
- uxControlPanel.ColumnDefinitions[6].Width = new GridLength(15 / (scale * ratio), GridUnitType.Pixel);
- uxControlPanel.ColumnDefinitions[8].Width = new GridLength(15 / (scale * ratio), GridUnitType.Pixel);
- ((ScaleTransform)uxPlayButton.RenderTransform).ScaleX = 1 / scale;
- ((ScaleTransform)uxPlayButton.RenderTransform).ScaleY = 1 / scale;
- }
- public void ReleaseResource()
- {
- mediaSource.Clock.Completed -= Video_Completed;
- mediaSource.MediaOpened -= MediaSource_MediaOpened;
- mediaSource.Clock.CurrentTimeInvalidated -= media_CurrentTimeInvalidated;
- mediaSource.Clock.Controller.Stop();
- mt.Source = null;
- mediaSource.Clock = null;
- mediaSource.Source = null;
- mediaSource = null;
- playerCreated.Remove(this);
- Console.WriteLine("WenVideoPlayer_ReleaseResource");
- }
- public FrameworkElement DetatchController()
- {
- if (uxControlPanel.Parent is Panel parentPanel)
- parentPanel.Children.Remove(uxControlPanel);
- uxControlPanel.IsVisibleChanged += (s, e) => {
- if (uxControlPanel.Visibility == Visibility.Visible)
- {
- toolbarHideTimer.Stop();
- toolbarHideTimer.Start();
- }
- };
- return uxControlPanel;
- }
- public VideoPlayer(Uri videoPath, VideoState beginBehavier = VideoState.play)
- {
- InitializeComponent();
- currentVideoState = beginBehavier;
- //Stylus.SetIsPressAndHoldEnabled(this, false);
- //this.IsManipulationEnabled = true;
- _videoPath = videoPath.OriginalString;
- this.beginBehavier = beginBehavier;
- this.Unloaded += WenVideoPlayer_Unloaded;
- //this.MouseLeave += WenVideoPlayer_MouseLeave;
- //create preview image
- ShellFile shellFile = ShellFile.FromFilePath(_videoPath);
- ((Image)uxCoverImageParent.Children[0]).Source = shellFile.Thumbnail.ExtraLargeBitmapSource;
- //((Image)uxCoverImageParent.Children[0]).Stretch = Stretch.None;
- //this.Height = Convert.ToDouble(shellFile.Properties.System.Video.FrameHeight.Value);
- //this.Width = Convert.ToDouble(shellFile.Properties.System.Video.FrameWidth.Value);
- videoSize.Width = Convert.ToDouble(shellFile.Properties.System.Video.FrameWidth.Value);
- videoSize.Height = Convert.ToDouble(shellFile.Properties.System.Video.FrameHeight.Value);
- double nanoseconds = -1;
- Double.TryParse(shellFile.Properties.System.Media.Duration.Value.ToString(), out nanoseconds);
- videoLength = nanoseconds == -1 ? -1 : nanoseconds / 10000000;
- this.Loaded += VideoPlayer_Loaded;
- //add video player
- mediaSource = new MediaElement();
- //mediaSource.Height = Convert.ToDouble(shellFile.Properties.System.Video.FrameHeight.Value);
- //mediaSource.Width = Convert.ToDouble(shellFile.Properties.System.Video.FrameWidth.Value);
- //mediaSource.Stretch = Stretch.Uniform;
- mt = new MediaTimeline(videoPath);
- mediaSource.Clock = mt.CreateClock();
- mediaSource.Clock.CurrentTimeInvalidated += media_CurrentTimeInvalidated;
- mediaSource.Clock.Completed += Video_Completed;
- mediaSource.LoadedBehavior = MediaState.Stop;
- mediaSource.MediaOpened += MediaSource_MediaOpened;
- mediaSource.VerticalAlignment = VerticalAlignment.Bottom;
- RenderOptions.SetBitmapScalingMode(mediaSource, BitmapScalingMode.HighQuality);
- //mediaSource.Margin = new Thickness(0, -10, 0, -10);
- toolbarHideTimer.Interval = TimeSpan.FromMilliseconds(timerInterval);
- toolbarHideTimer.Tick += AutoHideControlTimer_Tick;
- uxVideoPanel.Children.Add(mediaSource);
- this.UpdateLayout();
- playerCreated.Add(this);
- }
- private void VideoPlayer_Loaded(object sender, RoutedEventArgs e)
- {
- //video Height / Width info can get from this.Width & this.Height
- //videoRatio = (double)videoSize.Width / videoSize.Height;
- //double thisRatio = this.ActualWidth / this.ActualHeight;
- //if (videoRatio > thisRatio)
- //{
- // this.Height = this.ActualWidth / videoRatio;
- //}
- //else
- //{
- // this.Width = this.ActualHeight * videoRatio;
- //}
- uxVideoPanel.Height = this.Height;
- uxVideoPanel.Width = this.ActualWidth;
- //workaround
- mediaSource.Height = this.Height + 6;
- mediaSource.Width = this.ActualWidth + 6;
- }
- private void WenVideoPlayer_MouseLeave(object sender, RoutedEventArgs e)
- {
- return;
- mediaSource.Clock.Controller.Pause();
- uxControlPanel.Visibility = Visibility.Collapsed;
- uxVolumeGrid.Visibility = Visibility.Collapsed;
- uxPlayButtonParent.Visibility = Visibility.Visible;
- }
- private void WenVideoPlayer_Unloaded(object sender, RoutedEventArgs e)
- {
- if (mediaSource != null)
- {
- //mediaSource.Clock.Completed -= Video_Completed;
- //mediaSource.MediaOpened -= MediaSource_MediaOpened;
- //mediaSource.Clock.CurrentTimeInvalidated -= media_CurrentTimeInvalidated;
- mediaSource.Clock.Controller.Stop();
- mt.Source = null;
- //mediaSource.Clock = null;
- mediaSource.Source = null;
- //mediaSource = null;
- playerCreated.Remove(this);
- }
- }
- private void AutoHideControlTimer_Tick(object sender, EventArgs e)
- {
- uxControlPanel.Visibility = Visibility.Collapsed;
- uxVolumeGrid.Visibility = Visibility.Collapsed;
- toolbarHideTimer.Stop();
- }
- private void Video_Completed(object sender, EventArgs e)
- {
- mediaSource.Clock.Controller.Stop();
- uxControlPanel.Visibility = Visibility.Collapsed;
- uxVolumeGrid.Visibility = Visibility.Collapsed;
- if (toolbarHideTimer.IsEnabled)
- {
- toolbarHideTimer.Stop();
- }
- uxPlayButtonParent.Visibility = Visibility.Visible;
- OnVideoComplete?.Invoke(this, new EventArgs());
- }
- private void MediaSource_MediaOpened(object sender, RoutedEventArgs e)
- {
- mediaLoadComplete = true;
- mediaSource.Volume = uxVolumeSlider.Value / 10; //0.5;
- //uxVolumeSlider.Value = 5;
- //mt.Source.UserInfo.Count();
- if (beginBehavier == VideoState.play)
- {
- Play();
- }
- else if (beginBehavier == VideoState.stop)
- {
- mediaSource.Clock.Controller.Stop();
- Stop();
- }
- uxCoverImageParent.Visibility = Visibility.Collapsed;
- uxPlayButtonParent.Visibility = Visibility.Collapsed;
- //WenVideoPlayerIsPlaying += 1;
- }
- private void media_CurrentTimeInvalidated(object sender, EventArgs e)
- {
- if (stopRequest == true)
- {
- mediaSource.Clock.Controller.Stop();
- stopRequest = false;
- }
- if (mediaSource.NaturalDuration.HasTimeSpan && mediaSource.Clock.CurrentTime != null && progressSliderChanging != true)
- {
- uxProgressSlider.Value = 10 * mediaSource.Clock.CurrentTime.Value.TotalMilliseconds / mediaSource.NaturalDuration.TimeSpan.TotalMilliseconds;
- }
- }
- private void uxVideoPanel_TouchDown(object sender, TouchEventArgs e)
- {
- //if (uxControlPanel.Visibility == Visibility.Collapsed)
- //{
- // uxControlPanel.Visibility = Visibility.Visible;
- // toolbarHideTimer.Start();
- //}
- //else if (uxControlPanel.Visibility == Visibility.Visible)
- //{
- // uxControlPanel.Visibility = Visibility.Collapsed;
- // uxVolumeGrid.Visibility = Visibility.Collapsed;
- // if (toolbarHideTimer.IsEnabled)
- // {
- // toolbarHideTimer.Stop();
- // }
- // uxPlayButtonParent.Visibility = Visibility.Visible;
- // mediaSource.Clock.Controller.Pause();
- //}
- uxControlPanel.Visibility = Visibility.Visible;
- toolbarHideTimer.Start();
- }
- private void pause_TouchDown(object sender, TouchEventArgs e)
- {
- if (currentVideoState != VideoState.pause)
- {
- currentVideoState = VideoState.pause;
- mediaSource.Clock.Controller.Pause();
- uxControlPanel.Visibility = Visibility.Collapsed;
- uxVolumeGrid.Visibility = Visibility.Collapsed;
- uxPlayButtonParent.Visibility = Visibility.Visible;
- OnVideoStateChanged?.Invoke(this, VideoState.pause);
- }
- }
- private void stop_TouchDown(object sender, TouchEventArgs e)
- {
- if (currentVideoState != VideoState.stop)
- {
- currentVideoState = VideoState.stop;
- if (mediaLoadComplete == true)
- {
- mediaSource.Clock.Controller.Stop();
- uxControlPanel.Visibility = Visibility.Collapsed;
- uxVolumeGrid.Visibility = Visibility.Collapsed;
- if (toolbarHideTimer.IsEnabled)
- {
- toolbarHideTimer.Stop();
- }
- uxPlayButtonParent.Visibility = Visibility.Visible;
- uxCoverImageParent.Visibility = Visibility.Visible;
- }
- else
- {
- beginBehavier = VideoState.stop;
- }
- OnVideoStateChanged?.Invoke(this, VideoState.stop);
- }
- }
- private void uxPlayButton_TouchUp(object sender, TouchEventArgs e)
- {
- if (currentVideoState != VideoState.play)
- {
- currentVideoState = VideoState.play;
- uxPlayButtonParent.Visibility = Visibility.Collapsed;
- uxControlPanel.Visibility = Visibility.Collapsed;
- uxVolumeGrid.Visibility = Visibility.Collapsed;
- if (toolbarHideTimer.IsEnabled)
- {
- toolbarHideTimer.Stop();
- }
- if (mediaSource.Clock.CurrentState == ClockState.Stopped)
- {
- mediaSource.Clock.Controller.Pause();
- mediaSource.Clock.Controller.Resume();
- mediaSource.Clock.Controller.Begin();
- }
- else if (mediaSource.Clock.CurrentState == ClockState.Filling)
- {
- uxCoverImageParent.Visibility = Visibility.Collapsed;
- return;
- }
- if (mediaLoadComplete == false)
- {
- mediaSource.Clock.Controller.Begin();
- beginBehavier = VideoState.play;
- return;
- }
- if (mediaSource.Clock.IsPaused == true)
- {
- mediaSource.Clock.Controller.Resume();
- }
- else
- {
- mediaSource.Clock.Controller.Begin();
- }
- uxCoverImageParent.Visibility = Visibility.Collapsed;
- OnVideoStateChanged?.Invoke(this, VideoState.play);
- }
- }
- private void uxProgressSlider_TouchDown(object sender, TouchEventArgs e)
- {
- progressSliderChanging = true;
- mediaSource.Clock.Controller.Pause();
- Point pt = e.GetTouchPoint((UIElement)sender).Position;
- uxProgressSlider.Value = uxProgressSlider.Maximum * (pt.X) / uxProgressSlider.ActualWidth;
- e.Handled = true;
- Console.WriteLine("uxProgressSlider_TouchDown");
- }
- private void uxProgressSlider_TouchUp(object sender, TouchEventArgs e)
- {
- progressSliderChanging = false;
- mediaSource.Clock.Controller.Resume();
- }
- private void uxProgressSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
- {
- if (progressSliderChanging == true)
- {
- mediaSource.Clock.Controller.SeekAlignedToLastTick(new TimeSpan((long)(mediaSource.NaturalDuration.TimeSpan.Ticks * uxProgressSlider.Value / 10)), new System.Windows.Media.Animation.TimeSeekOrigin());
- }
- }
- private void uxProgressSlider_TouchMove(object sender, TouchEventArgs e)
- {
- progressSliderChanging = true;
- if (mediaSource.Clock.IsPaused == false)
- {
- mediaSource.Clock.Controller.Pause();
- }
- Point pt = e.GetTouchPoint((UIElement)sender).Position;
- uxProgressSlider.Value = uxProgressSlider.Maximum * (pt.X) / uxProgressSlider.ActualWidth;
- e.Handled = true;
- }
- private void Global_TouchUp(object sender, TouchEventArgs e)
- {
- if (progressSliderChanging == true)
- {
- progressSliderChanging = false;
- mediaSource.Clock.Controller.Resume();
- }
- if (e.Source is Grid && ((Grid)e.Source) == uxPlayButtonParent)
- {
- uxPlayButton_TouchUp(sender, e);
- }
- else if (toolbarHideTimer.IsEnabled == true)
- {
- toolbarHideTimer.Stop();
- toolbarHideTimer.Start();
- }
- }
- private void uxSound_TouchDown(object sender, TouchEventArgs e)
- {
- if (uxVolumeGrid.Visibility == Visibility.Collapsed)
- {
- uxVolumeGrid.Visibility = Visibility.Visible;
- ((Storyboard)FindResource("sbShowVolSlider")).Begin();
- }
- else
- {
- Storyboard sbBuf = ((Storyboard)FindResource("sbHideVolSlider"));
- sbBuf.Completed += delegate (object s, EventArgs se)
- {
- uxVolumeGrid.Visibility = Visibility.Collapsed;
- };
- sbBuf.Begin();
- }
- }
- private void uxVolumeGrid_TouchDown(object sender, TouchEventArgs e)
- {
- e.Handled = true;
- }
- private void uxVolumeGrid_TouchMove(object sender, TouchEventArgs e)
- {
- e.Handled = true;
- }
- private void uxVolumeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
- {
- setVolume(e.NewValue);
- }
- private void setVolume(double volume)
- {
- if (uxVolumeSlider.Value != volume)
- {
- uxVolumeSlider.Value = volume;
- if (volume == 0)
- {
- uxNoSound.Visibility = Visibility.Visible;
- uxSound.Visibility = Visibility.Collapsed;
- }
- else if (uxNoSound.Visibility == Visibility.Visible) //and e.NewValue != 0
- {
- uxNoSound.Visibility = Visibility.Collapsed;
- uxSound.Visibility = Visibility.Visible;
- }
- }
- if (mediaSource != null && mediaSource.IsLoaded)
- {
- mediaSource.Volume = volume / 10;
- }
-
- }
- private void ResetTimer(object sender, TouchEventArgs e)
- {
- if (toolbarHideTimer.IsEnabled == true)
- {
- toolbarHideTimer.Stop();
- toolbarHideTimer.Start();
- }
- }
- private void Grid_PreviewTouchUp(object sender, TouchEventArgs e)
- {
- if (manipulationLocked == true)
- {
- e.Handled = true;
- return;
- }
- }
- private void uxVolumeSlider_TouchDown(object sender, TouchEventArgs e)
- {
- Point pt = e.GetTouchPoint((UIElement)sender).Position;
- uxVolumeSlider.Value = uxVolumeSlider.Maximum * (uxVolumeSlider.ActualHeight - pt.Y) / uxVolumeSlider.ActualHeight;
- e.Handled = true;
- }
- private void uxVolumeSlider_TouchMove(object sender, TouchEventArgs e)
- {
- Point pt = e.GetTouchPoint((UIElement)sender).Position;
- uxVolumeSlider.Value = uxVolumeSlider.Maximum * (uxVolumeSlider.ActualHeight - pt.Y) / uxVolumeSlider.ActualHeight;
- //e.Handled = true;
- }
- }
- }
|