using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Threading; using System.Windows.Interop; using System.Windows.Media.Imaging; using System.Windows.Browser; using System.Reflection; using System.Net; using System.Windows.Resources; using System.Xml.Linq; using System.IO; using System.IO.IsolatedStorage; namespace VideoPlayer { public partial class Page : UserControl { //VideoPlayer;component/video.wmv public delegate void AnalyticLoadedHandler(object sender, EventArgs args); public event AnalyticLoadedHandler analyticLoadEvent = null; private DispatcherTimer _Timer = new DispatcherTimer(); private double _defaultPlayerWidth = 0.0; private double _defaultPlayerHeight = 0.0; private DateTime _lastClick = DateTime.Now; private closedCaption _cc = null; private bool _autoHideControls = true; public Page() { IsolatedStorageSettings iss = IsolatedStorageSettings.ApplicationSettings; InitializeComponent(); //this timer will be used to hide the controls when a user has moused away _Timer.Interval = new TimeSpan(0, 0, 5); _Timer.Tick += new EventHandler(_Timer_Tick); this.Loaded += new RoutedEventHandler(Page_Loaded); App.Current.Host.Content.FullScreenChanged += new System.EventHandler(Content_FullScreenChanged); } #region Handlers void Page_Loaded(object sender, RoutedEventArgs e) { if (App.Current.Resources["tracker"] != null) LoadAnalytics(); } void Media_CurrentStateChanged(object sender, RoutedEventArgs e) { if (mediaControls.Media.CurrentState == MediaElementState.Opening) { } } void LayoutRoot_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { // The the last click was within 500ms... if ((DateTime.Now - _lastClick).TotalMilliseconds < 500) { // Toggle fullscreen Application.Current.Host.Content.IsFullScreen = !Application.Current.Host.Content.IsFullScreen; _lastClick = DateTime.Now.AddSeconds(-1); } else { // Store the last click time _lastClick = DateTime.Now; } } void mediaControls_MarkerReached(object sender, TimelineMarker m) { if (_cc != null) { if (string.Compare(m.Type, "cc", StringComparison.InvariantCultureIgnoreCase) <= 0) { _cc.Update(m.Text); } } } void mediaControls_SoundChanged(object sender, bool isMuted) { if (mediaControls.EnableCC) { if (_cc == null) { _cc = new closedCaption(); _cc.VerticalAlignment = VerticalAlignment.Top; _cc.Margin = new Thickness(100, 100, 0, 0); LayoutRoot.Children.Add(_cc); } if (isMuted) { _cc.Visibility = Visibility.Visible; } else _cc.Visibility = Visibility.Collapsed; } } void mediaControls_MediaCompleted(object sender, EventArgs e) { Thumbnail.Visibility = Visibility.Visible; } void mediaControls_BufferingEnd(object sender, EventArgs e) { BigBuffer.Animation.Stop(); LargeSpinnerArea.Visibility = Visibility.Collapsed; } void mediaControls_BufferingStart(object sender, EventArgs e) { BigBuffer.Animation.Begin(); LargeSpinnerArea.Visibility = Visibility.Visible; } void mediaControls_StopClicked(object sender, EventArgs e) { PlayIcon.Visibility = Visibility.Visible; } void mediaControls_PauseClicked(object sender, EventArgs e) { PlayIcon.Visibility = Visibility.Visible; } void mediaControls_PlayClicked(object sender, EventArgs e) { Thumbnail.Visibility = Visibility.Collapsed; PlayIcon.Visibility = Visibility.Collapsed; } void Content_FullScreenChanged(object sender, EventArgs e) { if (App.Current.Host.Content.IsFullScreen == true) { double targetWidth = (double)App.Current.Host.Content.ActualWidth; double targetHeight = (double)App.Current.Host.Content.ActualHeight; this.Width = targetWidth; this.Height = targetHeight; mediaPlayer.Width = targetWidth; mediaPlayer.Height = targetHeight; } else { this.Width = _defaultPlayerWidth; this.Height = _defaultPlayerHeight; mediaPlayer.Width = _defaultPlayerWidth; mediaPlayer.Height = _defaultPlayerHeight; } RepositionCenterPlay(); } void mediaControls_FullScreenClicked(object sender, EventArgs e) { if (App.Current.Host.Content.IsFullScreen) { App.Current.Host.Content.IsFullScreen = false; } else { App.Current.Host.Content.IsFullScreen = true; } } void controlsContainer_MouseLeave(object sender, MouseEventArgs e) { if (_autoHideControls) { _Timer.Start(); } } void _Timer_Tick(object sender, EventArgs e) { controlsOut.Completed += new EventHandler(controlsOut_Completed); controlsOut.Begin(); } void controlsOut_Completed(object sender, EventArgs e) { controlsContainer.Visibility = Visibility.Collapsed; } void LayoutRoot2_MouseEnter(object sender, MouseEventArgs e) { if (_autoHideControls) { if (controlsContainer.Visibility == Visibility.Collapsed) { controlsContainer.Visibility = Visibility.Visible; controlsIn.Begin(); } _Timer.Stop(); } } private void PlayIcon_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { mediaControls.CenterPlay(); } #endregion private void RepositionCenterPlay() { double newLeft = (App.Current.Host.Content.ActualWidth / 2) - 50; double newTop = (App.Current.Host.Content.ActualHeight / 2) - 50; PlayIcon.SetValue(Canvas.LeftProperty, newLeft); PlayIcon.SetValue(Canvas.TopProperty, newTop); LargeSpinnerArea.SetValue(Canvas.LeftProperty, newLeft); LargeSpinnerArea.SetValue(Canvas.TopProperty, newTop); } [ScriptableMember] public void SeekPlayback(string time) { TimeSpan tsTime = TimeSpan.Parse(time); mediaControls.Seek(tsTime); } #region Load Analytics private List asms; private bool waitForAnalyticsLoad = true; private DownloadInfo info = new DownloadInfo(); private Object analytics = null; private void LoadAnalytics() { WebClient client = new WebClient(); string url = App.Current.Resources["anvatoanalyticsplugin"] as String; if(url == "" || url == null) url = "http://plugins.anvato.com/1.7/anvatoanalytics.slv.player.1.x.xap"; string fileFormat = url.Split('.')[url.Split('.').Length-1]; if(fileFormat == "xap") client.OpenReadCompleted += new OpenReadCompletedEventHandler(xapFile_OpenReadCompleted); if (fileFormat == "dll") client.OpenReadCompleted += new OpenReadCompletedEventHandler(dllFile_OpenReadCompleted); client.OpenReadAsync(new Uri(url, UriKind.RelativeOrAbsolute)); } void dllFile_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { asms = new List(); AssemblyPart asmPart = new AssemblyPart(); // StreamResourceInfo streamInfo = Application.GetResourceStream(new StreamResourceInfo(e.Result, "application/binary"), new Uri(e., UriKind.Relative)); Assembly asm = asmPart.Load(e.Result); if (asm != null) asms.Add(asm); if (waitForAnalyticsLoad) loadAssemblies(); } void xapFile_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e) { string appManifest = new StreamReader(Application.GetResourceStream(new StreamResourceInfo(e.Result, null), new Uri("AppManifest.xaml", UriKind.Relative)).Stream).ReadToEnd(); XElement deploy = XDocument.Parse(appManifest).Root; List parts = (from assemblyParts in deploy.Elements().Elements() select assemblyParts).ToList(); Assembly asm = null; foreach (XElement xe in parts) { string source = xe.Attribute("Source").Value; AssemblyPart asmPart = new AssemblyPart(); StreamResourceInfo streamInfo = Application.GetResourceStream(new StreamResourceInfo(e.Result, "application/binary"), new Uri(source, UriKind.Relative)); if (source == "AnvatoAnalytics.dll") { asm = asmPart.Load(streamInfo.Stream); } else { asmPart.Load(streamInfo.Stream); } } asms = new List(); if (asm != null) asms.Add(asm); if (waitForAnalyticsLoad) loadAssemblies(); } private void loadAssemblies() { if (asms == null) { waitForAnalyticsLoad = true; return; } foreach (Assembly asm in asms) { try { if (asm == null) continue; LoadAssembly(asm); } catch (Exception ex) { } } } public void LoadAssembly(Assembly asm) { info.externalMethod = "AnvatoAnalytics.SLAnalytics"; info.parameters = null; if (asm == null) { throw new Exception("Invalid plugin dll"); } Type[] pTypes = asm.GetTypes(); foreach (Type type in pTypes) { string[] typeNames = info.externalMethod.Split('.'); string typeName = typeNames[0] + '.' + typeNames[1]; if (type.FullName != typeName) continue; analytics = Activator.CreateInstance(type); info.analyticsMethods = type.GetMethods(); } Object[] pList = new object[1]; pList[0] = (App.Current.Resources["debug"] as String) == "true"; callAnalyticsFunction("set_debug", pList); pList = new object[1]; pList[0] = (App.Current.Resources["diagnosis"] as String) == "true"; callAnalyticsFunction("set_diagnosis", pList); pList = new object[1]; pList[0] = App.Current.Resources["title"] as String; callAnalyticsFunction("set_videoTitle", pList); pList = new object[7]; pList[0] = mediaPlayer; pList[1] = App.Current.Resources["tracker"] as String; pList[2] = null; pList[3] = Application.Current.Host.Source.AbsoluteUri; pList[4] = "sl"; pList[5] = "3"; pList[6] = null; callAnalyticsFunction("initialize", pList); pList = new object[5]; pList[0] = (App.Current.Resources["m"] as Uri).AbsoluteUri; pList[1] = App.Current.Resources["title"] as String; pList[2] = null; pList[3] = null; pList[4] = null; callAnalyticsFunction("onLoad", pList); App.Current.Host.Content.FullScreenChanged += new System.EventHandler(FullScreenAnalyticsHandler); mediaControls.sliderVolume.ValueChanged += new RoutedPropertyChangedEventHandler(sliderVolume_ValueChangedAnalyticsHandler); mediaControls.sliderTimeline.MyValueChanged += new RoutedPropertyChangedEventHandler(sliderTimeline_ValueChangedAnalyticsHandler); analyticLoadEvent += new AnalyticLoadedHandler(Page_analyticLoadEvent); analyticLoadEvent(this,new EventArgs()); } void Page_analyticLoadEvent(object sender, EventArgs args) { LayoutRoot2.MouseEnter += new MouseEventHandler(LayoutRoot2_MouseEnter); LayoutRoot.MouseLeftButtonUp += new MouseButtonEventHandler(LayoutRoot_MouseLeftButtonUp); controlsContainer.MouseLeave += new MouseEventHandler(controlsContainer_MouseLeave); // TODO: check if there isn't one and show an image mediaPlayer.Source = App.Current.Resources["m"] as Uri; // mediaControls.sliderVolume.ValueChanged += new RoutedPropertyChangedEventHandler(sliderVolume_ValueChanged); #region Additional Startup Params if (App.Current.Resources.Contains("autostart")) { mediaPlayer.AutoPlay = Convert.ToBoolean(App.Current.Resources["autostart"]); } if (App.Current.Resources.Contains("thumbnail")) { ImageSource imgsrc = new System.Windows.Media.Imaging.BitmapImage(App.Current.Resources["thumbnail"] as Uri); ThumbnailImage.SetValue(Image.SourceProperty, imgsrc); Thumbnail.Visibility = Visibility.Visible; } if (App.Current.Resources.Contains("markers")) { mediaControls.EnableMarkers = Convert.ToBoolean(App.Current.Resources["markers"]); } if (App.Current.Resources.Contains("cc")) { mediaControls.EnableCC = Convert.ToBoolean(App.Current.Resources["cc"]); } if (App.Current.Resources.Contains("markerpath")) { mediaControls.MarkerPath = App.Current.Resources["markerpath"] as Uri; } if (App.Current.Resources.Contains("muted")) { mediaPlayer.IsMuted = Convert.ToBoolean(App.Current.Resources["muted"]); } if (App.Current.Resources.Contains("autohide")) { _autoHideControls = Convert.ToBoolean(App.Current.Resources["autohide"]); } if (App.Current.Resources.Contains("canscrub")) { mediaControls.sliderTimeline.IsHitTestVisible = Convert.ToBoolean(App.Current.Resources["canscrub"]); } #endregion mediaControls.Media = mediaPlayer; _defaultPlayerWidth = this.Width; _defaultPlayerHeight = this.Height; RepositionCenterPlay(); mediaControls.Media.CurrentStateChanged += new RoutedEventHandler(Media_CurrentStateChanged); mediaControls.FullScreenClicked += new mediaControl.EventHandler(mediaControls_FullScreenClicked); mediaControls.PlayClicked += new mediaControl.EventHandler(mediaControls_PlayClicked); mediaControls.PauseClicked += new mediaControl.EventHandler(mediaControls_PauseClicked); mediaControls.StopClicked += new mediaControl.EventHandler(mediaControls_StopClicked); mediaControls.BufferingStart += new mediaControl.EventHandler(mediaControls_BufferingStart); mediaControls.BufferingEnd += new mediaControl.EventHandler(mediaControls_BufferingEnd); mediaControls.MediaCompleted += new mediaControl.EventHandler(mediaControls_MediaCompleted); mediaControls.SoundChanged += new mediaControl.SoundEventHandler(mediaControls_SoundChanged); mediaControls.MarkerReached += new mediaControl.MarkerEventHandler(mediaControls_MarkerReached); controlsContainer.Visibility = Visibility.Visible; controlsIn.Begin(); } void mediaControls_PlayClickedAnalyticsHandler(object sender, EventArgs e) { Object[] pList = new object[2]; pList[0] = "upl"; pList[1] = ""; callAnalyticsFunction("dispatchAnalyticEvent", pList); } void mediaControls_PauseClickedAnalyticsHandler(object sender, EventArgs e) { if (mediaPlayer.Position.TotalSeconds != mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds) { Object[] pList = new object[2]; pList[0] = "upa"; pList[1] = ""; callAnalyticsFunction("dispatchAnalyticEvent", pList); } } void sliderTimeline_ValueChangedAnalyticsHandler(object sender, RoutedPropertyChangedEventArgs e) { Object[] pList = new object[2]; pList[0] = "usk"; pList[1] = e.NewValue.ToString(); callAnalyticsFunction("dispatchAnalyticEvent", pList); } void sliderVolume_ValueChangedAnalyticsHandler(object sender, RoutedPropertyChangedEventArgs e) { Object[] pList = new object[2]; pList[0] = "uvl"; pList[1] = e.NewValue.ToString(); callAnalyticsFunction("dispatchAnalyticEvent", pList); } void mediaControls_SoundChangedAnalyticsHandler(object sender, bool isMuted) { Object[] pList = new object[2]; pList[0] = "uvl"; pList[1] = "0"; callAnalyticsFunction("dispatchAnalyticEvent", pList); } void FullScreenAnalyticsHandler(object sender, EventArgs e) { Object[] pList = new object[2]; if (App.Current.Host.Content.IsFullScreen == true) { pList[0] = "ufo"; pList[1] = ""; callAnalyticsFunction("dispatchAnalyticEvent", pList); } else { pList[0] = "ufc"; pList[1] = ""; callAnalyticsFunction("dispatchAnalyticEvent", pList); } } void callAnalyticsFunction(string functionName, Object[] parameters) { foreach (MethodInfo method in info.analyticsMethods) { if (!method.IsVirtual && method.Name == functionName) { ParameterInfo[] prms = method.GetParameters(); if (prms.Length == 0) { analytics.GetType().InvokeMember(method.Name, BindingFlags.Default | BindingFlags.InvokeMethod, null, analytics, new object[] { }).ToString(); break; } else if (prms.Length > 0) { analytics.GetType().InvokeMember(method.Name, BindingFlags.Default | BindingFlags.InvokeMethod, null, analytics, parameters); break; } } } } #endregion } public class DownloadInfo { public string externalMethod; public Object[] parameters; public WebClient WebClient; public MethodInfo[] analyticsMethods; } }