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 _json serializer /// private readonly IJsonSerializer _jsonSerializer; /// /// The _logger /// private readonly ILogger _logger; /// /// The _app host /// private readonly IApplicationHost _appHost; /// /// Initializes a new instance of the class. /// /// The json serializer. /// The logger. /// The app host. /// logger public MainWindow(IJsonSerializer jsonSerializer, ILogger logger, IApplicationHost appHost) { if (jsonSerializer == null) { throw new ArgumentNullException("jsonSerializer"); } if (logger == null) { throw new ArgumentNullException("logger"); } _jsonSerializer = jsonSerializer; _logger = logger; _appHost = appHost; 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; Kernel.Instance.LoggerLoaded += LoadLogWindow; Kernel.Instance.HasPendingRestartChanged += Instance_HasPendingRestartChanged; 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; }); } /// /// Sets visibility of the restart message when the kernel value changes /// /// The source of the event. /// The instance containing the event data. void Instance_HasPendingRestartChanged(object sender, EventArgs e) { Dispatcher.InvokeAsync(() => { MbTaskbarIcon.ToolTipText = Kernel.Instance.HasPendingRestart ? "Media Browser Server - Please restart to finish updating." : "Media Browser Server"; }); } /// /// 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) { Kernel.Instance.LibraryManager.LibraryChanged -= Instance_LibraryChanged; Kernel.Instance.LibraryManager.LibraryChanged += Instance_LibraryChanged; if (_appHost.IsFirstRun) { LaunchStartupWizard(); } } /// /// Launches the startup wizard. /// private void LaunchStartupWizard() { App.OpenDashboardPage("wizardStart.html"); } /// /// 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:" + Controller.Kernel.Instance.Configuration.HttpServerPortNumber + "/" + Controller.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) { (new LibraryExplorer(_jsonSerializer, _logger, _appHost)).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) { App.OpenDashboard(); } /// /// 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) { App.OpenDashboardPage("index.html"); } /// /// 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 } }