using MediaBrowser.Common.Kernel; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.ServerApplication.Controls; using MediaBrowser.ServerApplication.Logging; using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Threading; using System.Windows; using System.Windows.Controls.Primitives; using System.Windows.Threading; namespace MediaBrowser.ServerApplication { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window, INotifyPropertyChanged { /// /// Holds the list of new items to display when the NewItemTimer expires /// private readonly List _newlyAddedItems = new List(); /// /// The amount of time to wait before showing a new item notification /// This allows us to group items together into one notification /// private const int NewItemDelay = 60000; /// /// The current new item timer /// /// The new item timer. private Timer NewItemTimer { get; set; } /// /// The _logger /// private readonly ILogger _logger; /// /// The _app host /// private readonly IApplicationHost _appHost; /// /// The _log manager /// private readonly ILogManager _logManager; private readonly ILibraryManager _libraryManager; /// /// Initializes a new instance of the class. /// /// The json serializer. /// The logger. /// The app host. /// logger public MainWindow(ILogManager logManager, IApplicationHost appHost, ILibraryManager libraryManager) { if (logManager == null) { throw new ArgumentNullException("logManager"); } _logger = logManager.GetLogger("MainWindow"); _appHost = appHost; _logManager = logManager; _libraryManager = libraryManager; InitializeComponent(); Loaded += MainWindowLoaded; } /// /// Mains the window loaded. /// /// The sender. /// The instance containing the event data. void MainWindowLoaded(object sender, RoutedEventArgs e) { DataContext = this; Instance_ConfigurationUpdated(null, EventArgs.Empty); Kernel.Instance.ReloadCompleted += KernelReloadCompleted; _logManager.LoggerLoaded += LoadLogWindow; Kernel.Instance.ConfigurationUpdated += Instance_ConfigurationUpdated; } /// /// Handles the ConfigurationUpdated event of the Instance control. /// /// The source of the event. /// The instance containing the event data. void Instance_ConfigurationUpdated(object sender, EventArgs e) { Dispatcher.InvokeAsync(() => { var developerToolsVisibility = Kernel.Instance.Configuration.EnableDeveloperTools ? Visibility.Visible : Visibility.Collapsed; separatorDeveloperTools.Visibility = developerToolsVisibility; cmdReloadServer.Visibility = developerToolsVisibility; cmOpenExplorer.Visibility = developerToolsVisibility; var logWindow = App.Instance.Windows.OfType().FirstOrDefault(); if ((logWindow == null && Kernel.Instance.Configuration.ShowLogWindow) || (logWindow != null && !Kernel.Instance.Configuration.ShowLogWindow)) { _logManager.ReloadLogger(Kernel.Instance.Configuration.EnableDebugLevelLogging ? LogSeverity.Debug : LogSeverity.Info); } }); } /// /// Handles the LibraryChanged event of the Instance control. /// /// The source of the event. /// The instance containing the event data. void Instance_LibraryChanged(object sender, ChildrenChangedEventArgs e) { var newItems = e.ItemsAdded.Where(i => !i.IsFolder).ToList(); // Use a timer to prevent lots of these notifications from showing in a short period of time if (newItems.Count > 0) { lock (_newlyAddedItems) { _newlyAddedItems.AddRange(newItems); if (NewItemTimer == null) { NewItemTimer = new Timer(NewItemTimerCallback, null, NewItemDelay, Timeout.Infinite); } else { NewItemTimer.Change(NewItemDelay, Timeout.Infinite); } } } } /// /// Called when the new item timer expires /// /// The state. private void NewItemTimerCallback(object state) { List newItems; // Lock the list and release all resources lock (_newlyAddedItems) { newItems = _newlyAddedItems.ToList(); _newlyAddedItems.Clear(); NewItemTimer.Dispose(); NewItemTimer = null; } // Show the notification if (newItems.Count == 1) { Dispatcher.InvokeAsync(() => MbTaskbarIcon.ShowCustomBalloon(new ItemUpdateNotification(_logger) { DataContext = newItems[0] }, PopupAnimation.Slide, 6000)); } else if (newItems.Count > 1) { Dispatcher.InvokeAsync(() => MbTaskbarIcon.ShowCustomBalloon(new MultiItemUpdateNotification(_logger) { DataContext = newItems }, PopupAnimation.Slide, 6000)); } } /// /// Loads the log window. /// /// The sender. /// The instance containing the event data. void LoadLogWindow(object sender, EventArgs args) { CloseLogWindow(); Dispatcher.InvokeAsync(() => { // Add our log window if specified if (Kernel.Instance.Configuration.ShowLogWindow) { Trace.Listeners.Add(new WindowTraceListener(new LogWindow(Kernel.Instance))); } else { Trace.Listeners.Remove("MBLogWindow"); } // Set menu option indicator cmShowLogWindow.IsChecked = Kernel.Instance.Configuration.ShowLogWindow; }, DispatcherPriority.Normal); } /// /// Closes the log window. /// void CloseLogWindow() { Dispatcher.InvokeAsync(() => { foreach (var win in Application.Current.Windows.OfType()) { win.Close(); } }); } /// /// Kernels the reload completed. /// /// The sender. /// The e. void KernelReloadCompleted(object sender, EventArgs e) { _libraryManager.LibraryChanged -= Instance_LibraryChanged; _libraryManager.LibraryChanged += Instance_LibraryChanged; if (_appHost.IsFirstRun) { LaunchStartupWizard(); } } /// /// Launches the startup wizard. /// private void LaunchStartupWizard() { var user = _appHost.Resolve().Users.FirstOrDefault(u => u.Configuration.IsAdministrator); App.OpenDashboardPage("wizardStart.html", user); } /// /// Handles the Click event of the cmdApiDocs control. /// /// The source of the event. /// The instance containing the event data. void cmdApiDocs_Click(object sender, EventArgs e) { App.OpenUrl("http://localhost:" + Kernel.Instance.Configuration.HttpServerPortNumber + "/" + Kernel.Instance.WebApplicationName + "/metadata"); } /// /// Occurs when [property changed]. /// public event PropertyChangedEventHandler PropertyChanged; /// /// Called when [property changed]. /// /// The info. public void OnPropertyChanged(String info) { if (PropertyChanged != null) { try { PropertyChanged(this, new PropertyChangedEventArgs(info)); } catch (Exception ex) { _logger.ErrorException("Error in event handler", ex); } } } #region Context Menu events /// /// Handles the click event of the cmOpenExplorer control. /// /// The source of the event. /// The instance containing the event data. private void cmOpenExplorer_click(object sender, RoutedEventArgs e) { var explorer = (LibraryExplorer)_appHost.CreateInstance(typeof(LibraryExplorer)); explorer.Show(); } /// /// Handles the click event of the cmOpenDashboard control. /// /// The source of the event. /// The instance containing the event data. private void cmOpenDashboard_click(object sender, RoutedEventArgs e) { var user = _appHost.Resolve().Users.FirstOrDefault(u => u.Configuration.IsAdministrator); App.OpenDashboard(user); } /// /// Handles the click event of the cmVisitCT control. /// /// The source of the event. /// The instance containing the event data. private void cmVisitCT_click(object sender, RoutedEventArgs e) { App.OpenUrl("http://community.mediabrowser.tv/"); } /// /// Handles the click event of the cmdBrowseLibrary control. /// /// The source of the event. /// The instance containing the event data. private void cmdBrowseLibrary_click(object sender, RoutedEventArgs e) { var user = _appHost.Resolve().Users.FirstOrDefault(u => u.Configuration.IsAdministrator); App.OpenDashboardPage("index.html", user); } /// /// Handles the click event of the cmExit control. /// /// The source of the event. /// The instance containing the event data. private void cmExit_click(object sender, RoutedEventArgs e) { Application.Current.Shutdown(); } /// /// Handles the click event of the cmdReloadServer control. /// /// The source of the event. /// The instance containing the event data. private void cmdReloadServer_click(object sender, RoutedEventArgs e) { App.Instance.Restart(); } /// /// Handles the click event of the CmShowLogWindow control. /// /// The source of the event. /// The instance containing the event data. private void CmShowLogWindow_click(object sender, RoutedEventArgs e) { Kernel.Instance.Configuration.ShowLogWindow = !Kernel.Instance.Configuration.ShowLogWindow; Kernel.Instance.SaveConfiguration(); LoadLogWindow(sender, e); } #endregion } }