Beispiel #1
0
        public static IEnumerable <Share> GetShares()
        {
            ILocalSharesManagement sharesManagement = ServiceRegistration.Get <ILocalSharesManagement>();

            return(sharesManagement.Shares.Values);
        }
Beispiel #2
0
        public override void UpdateShare(RelocationMode relocationMode)
        {
            ILocalSharesManagement sharesManagement = ServiceRegistration.Get <ILocalSharesManagement>();

            sharesManagement.UpdateShare(_origShare.ShareId, ChoosenResourcePath, ShareName, GetMediaCategoriesCleanedUp(), relocationMode);
        }
Beispiel #3
0
        public override void ReImportShare()
        {
            ILocalSharesManagement sharesManagement = ServiceRegistration.Get <ILocalSharesManagement>();

            sharesManagement.ReImportShare(_origShare.ShareId);
        }
Beispiel #4
0
        protected override bool ShareNameExists(string shareName)
        {
            ILocalSharesManagement sharesManagement = ServiceRegistration.Get <ILocalSharesManagement>();

            return(sharesManagement.Shares.Values.Any(share => (_origShare == null || share.ShareId != _origShare.ShareId) && share.Name == shareName));
        }
Beispiel #5
0
        protected override bool SharePathExists(ResourcePath sharePath)
        {
            ILocalSharesManagement sharesManagement = ServiceRegistration.Get <ILocalSharesManagement>();

            return(sharesManagement.Shares.Values.Any(share => (_origShare == null || share.ShareId != _origShare.ShareId) && share.BaseResourcePath == sharePath));
        }
        void OnMessageReceived(AsynchronousMessageQueue queue, SystemMessage message)
        {
            if (message.ChannelName == SharesMessaging.CHANNEL)
            {
                IContentDirectory           cd          = ContentDirectory;
                SharesMessaging.MessageType messageType =
                    (SharesMessaging.MessageType)message.MessageType;
                IImporterWorker importerWorker = ServiceRegistration.Get <IImporterWorker>();
                Share           share;
                switch (messageType)
                {
                case SharesMessaging.MessageType.ShareAdded:
                    share = (Share)message.MessageData[SharesMessaging.SHARE];
                    if (cd != null)
                    {
                        cd.RegisterShareAsync(share);
                    }
                    importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true);
                    break;

                case SharesMessaging.MessageType.ShareRemoved:
                    share = (Share)message.MessageData[SharesMessaging.SHARE];
                    importerWorker.CancelJobsForPath(share.BaseResourcePath);
                    if (cd != null)
                    {
                        cd.RemoveShareAsync(share.ShareId);
                    }
                    break;

                case SharesMessaging.MessageType.ShareChanged:
                    RelocationMode relocationMode = (RelocationMode)message.MessageData[SharesMessaging.RELOCATION_MODE];
                    share = (Share)message.MessageData[SharesMessaging.SHARE];
                    importerWorker.CancelJobsForPath(share.BaseResourcePath);
                    if (cd == null)
                    {
                        ISettingsManager         settingsManager = ServiceRegistration.Get <ISettingsManager>();
                        ServerConnectionSettings settings        = settingsManager.Load <ServerConnectionSettings>();
                        RelocationMode           oldMode;
                        if (settings.CachedSharesUpdates.TryGetValue(share.ShareId, out oldMode) && oldMode == RelocationMode.ClearAndReImport)
                        {
                            // ClearAndReimport is stronger than Relocate, use ClearAndReImport
                            relocationMode = oldMode;
                        }
                        settings.CachedSharesUpdates[share.ShareId] = relocationMode;
                        settingsManager.Save(settings);
                    }
                    else
                    {
                        cd.UpdateShareAsync(share.ShareId, share.BaseResourcePath, share.Name, share.UseShareWatcher, share.MediaCategories, relocationMode);
                        switch (relocationMode)
                        {
                        case RelocationMode.ClearAndReImport:
                            importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true);
                            break;

                        case RelocationMode.Relocate:
                            importerWorker.ScheduleRefresh(share.BaseResourcePath, share.MediaCategories, true);
                            break;
                        }
                    }
                    break;

                case SharesMessaging.MessageType.ReImportShare:
                    share = (Share)message.MessageData[SharesMessaging.SHARE];
                    importerWorker.ScheduleRefresh(share.BaseResourcePath, share.MediaCategories, true);
                    break;
                }
            }
            else if (message.ChannelName == ImporterWorkerMessaging.CHANNEL)
            {
                IContentDirectory cd = ContentDirectory;
                ImporterWorkerMessaging.MessageType messageType = (ImporterWorkerMessaging.MessageType)message.MessageType;
                switch (messageType)
                {
                case ImporterWorkerMessaging.MessageType.ImportStarted:
                case ImporterWorkerMessaging.MessageType.ImportCompleted:
                    if (cd == null)
                    {
                        break;
                    }
                    ResourcePath           path   = (ResourcePath)message.MessageData[ImporterWorkerMessaging.RESOURCE_PATH];
                    ILocalSharesManagement lsm    = ServiceRegistration.Get <ILocalSharesManagement>();
                    ICollection <Share>    shares = lsm.Shares.Values;
                    Share share = shares.BestContainingPath(path);
                    if (share == null)
                    {
                        break;
                    }
                    if (messageType == ImporterWorkerMessaging.MessageType.ImportStarted)
                    {
                        cd.ClientStartedShareImportAsync(share.ShareId);
                    }
                    else
                    {
                        cd.ClientCompletedShareImportAsync(share.ShareId);
                    }
                    break;
                }
            }
            else if (message.ChannelName == ServerStateMessaging.CHANNEL)
            {
                //Check if Tv Server state has changed and update if necessary
                ServerStateMessaging.MessageType messageType = (ServerStateMessaging.MessageType)message.MessageType;
                if (messageType == ServerStateMessaging.MessageType.StatesChanged)
                {
                    var states = message.MessageData[ServerStateMessaging.STATES] as IDictionary <Guid, object>;
                    if (states != null && states.ContainsKey(ShareImportServerState.STATE_ID))
                    {
                        ShareImportServerState importState = states[ShareImportServerState.STATE_ID] as ShareImportServerState;
                        if (importState != null)
                        {
                            List <ShareImportState> shareStates = new List <ShareImportState>(importState.Shares);
                            lock (_syncObj)
                            {
                                UpdateCurrentlyImportingShares(shareStates.Where(s => s.IsImporting).Select(s => s.ShareId).ToList());
                                UpdateCurrentlyImportingSharesProgresses(shareStates.Where(s => s.IsImporting).ToDictionary(s => s.ShareId, s => s.Progress));
                            }
                        }
                    }
                    else if (states != null && states.ContainsKey(DatabaseUpgradeServerState.STATE_ID))
                    {
                        DatabaseUpgradeServerState upgradeState = states[DatabaseUpgradeServerState.STATE_ID] as DatabaseUpgradeServerState;
                        if (upgradeState != null && !upgradeState.IsUpgrading && upgradeState.Progress == 100)
                        {
                            ServerConnectionMessaging.SendServerConnectionStateChangedMessage(ServerConnectionMessaging.MessageType.HomeServerDisconnected);
                            ServerConnectionMessaging.SendServerConnectionStateChangedMessage(ServerConnectionMessaging.MessageType.HomeServerConnected);
                        }
                    }
                }
            }
        }
        void OnMessageReceived(AsynchronousMessageQueue queue, SystemMessage message)
        {
            if (message.ChannelName == SharesMessaging.CHANNEL)
            {
                IContentDirectory           cd          = ContentDirectory;
                SharesMessaging.MessageType messageType =
                    (SharesMessaging.MessageType)message.MessageType;
                IImporterWorker importerWorker = ServiceRegistration.Get <IImporterWorker>();
                Share           share;
                switch (messageType)
                {
                case SharesMessaging.MessageType.ShareAdded:
                    share = (Share)message.MessageData[SharesMessaging.SHARE];
                    if (cd != null)
                    {
                        cd.RegisterShare(share);
                    }
                    importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true);
                    break;

                case SharesMessaging.MessageType.ShareRemoved:
                    share = (Share)message.MessageData[SharesMessaging.SHARE];
                    importerWorker.CancelJobsForPath(share.BaseResourcePath);
                    if (cd != null)
                    {
                        cd.RemoveShare(share.ShareId);
                    }
                    break;

                case SharesMessaging.MessageType.ShareChanged:
                    RelocationMode relocationMode = (RelocationMode)message.MessageData[SharesMessaging.RELOCATION_MODE];
                    share = (Share)message.MessageData[SharesMessaging.SHARE];
                    importerWorker.CancelJobsForPath(share.BaseResourcePath);
                    if (cd == null)
                    {
                        ISettingsManager         settingsManager = ServiceRegistration.Get <ISettingsManager>();
                        ServerConnectionSettings settings        = settingsManager.Load <ServerConnectionSettings>();
                        RelocationMode           oldMode;
                        if (settings.CachedSharesUpdates.TryGetValue(share.ShareId, out oldMode) && oldMode == RelocationMode.ClearAndReImport)
                        {
                            // ClearAndReimport is stronger than Relocate, use ClearAndReImport
                            relocationMode = oldMode;
                        }
                        settings.CachedSharesUpdates[share.ShareId] = relocationMode;
                        settingsManager.Save(settings);
                    }
                    else
                    {
                        cd.UpdateShare(share.ShareId, share.BaseResourcePath, share.Name, share.MediaCategories, relocationMode);
                        switch (relocationMode)
                        {
                        case RelocationMode.ClearAndReImport:
                            importerWorker.ScheduleImport(share.BaseResourcePath, share.MediaCategories, true);
                            break;

                        case RelocationMode.Relocate:
                            importerWorker.ScheduleRefresh(share.BaseResourcePath, share.MediaCategories, true);
                            break;
                        }
                    }
                    break;

                case SharesMessaging.MessageType.ReImportShare:
                    share = (Share)message.MessageData[SharesMessaging.SHARE];
                    importerWorker.ScheduleRefresh(share.BaseResourcePath, share.MediaCategories, true);
                    break;
                }
            }
            else if (message.ChannelName == ImporterWorkerMessaging.CHANNEL)
            {
                IContentDirectory cd = ContentDirectory;
                ImporterWorkerMessaging.MessageType messageType = (ImporterWorkerMessaging.MessageType)message.MessageType;
                switch (messageType)
                {
                case ImporterWorkerMessaging.MessageType.ImportStarted:
                case ImporterWorkerMessaging.MessageType.ImportCompleted:
                    if (cd == null)
                    {
                        break;
                    }
                    ResourcePath           path   = (ResourcePath)message.MessageData[ImporterWorkerMessaging.RESOURCE_PATH];
                    ILocalSharesManagement lsm    = ServiceRegistration.Get <ILocalSharesManagement>();
                    ICollection <Share>    shares = lsm.Shares.Values;
                    Share share = shares.BestContainingPath(path);
                    if (share == null)
                    {
                        break;
                    }
                    if (messageType == ImporterWorkerMessaging.MessageType.ImportStarted)
                    {
                        cd.ClientStartedShareImport(share.ShareId);
                    }
                    else
                    {
                        cd.ClientCompletedShareImport(share.ShareId);
                    }
                    break;
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// The main entry point for the MP2 client application.
        /// </summary>
        private static void Main(params string[] args)
        {
            Thread.CurrentThread.Name = "Main";

            // Parse command line options
            var mpOptions = new CommandLineOptions();
            var parser    = new CommandLine.Parser(with => with.HelpWriter = Console.Out);

            parser.ParseArgumentsStrict(args, mpOptions, () => Environment.Exit(1));

            // Check if another instance is already running
            if (SingleInstanceHelper.IsAlreadyRunning(MUTEX_ID, out _mutex))
            {
                _mutex = null;
                // Set focus on previously running app
                SingleInstanceHelper.SwitchToCurrentInstance(SingleInstanceHelper.SHOW_MP2_CLIENT_MESSAGE);
                // Stop current instance
                Console.Out.WriteLine("Application already running.");
                Environment.Exit(2);
            }

#if !DEBUG
            string logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Team MediaPortal\MP2-Client\Log");
#endif

            Application.ThreadException += LauncherExceptionHandling.Application_ThreadException;
            AppDomain.CurrentDomain.UnhandledException += LauncherExceptionHandling.CurrentDomain_UnhandledException;
            TaskScheduler.UnobservedTaskException      += LauncherExceptionHandling.TaskScheduler_UnobservedTaskException;

            SystemStateService systemStateService = new SystemStateService();
            ServiceRegistration.Set <ISystemStateService>(systemStateService);
            systemStateService.SwitchSystemState(SystemState.Initializing, false);

            try
            {
#if !DEBUG
                SplashScreen splashScreen = null;
#endif
                ILogger logger = null;
                try
                {
                    // Check if user wants to override the default Application Data location.
                    ApplicationCore.RegisterVitalCoreServices(true, mpOptions.DataDirectory);

#if !DEBUG
                    splashScreen = CreateSplashScreen();
                    splashScreen.ShowSplashScreen();
#endif

                    ApplicationCore.RegisterCoreServices();

                    logger = ServiceRegistration.Get <ILogger>();

#if !DEBUG
                    IPathManager pathManager = ServiceRegistration.Get <IPathManager>();
                    logPath = pathManager.GetPath("<LOG>");
#endif

                    UiExtension.RegisterUiServices();
                }
                catch (Exception e)
                {
                    if (logger != null)
                    {
                        logger.Critical("Error starting application", e);
                    }
                    systemStateService.SwitchSystemState(SystemState.ShuttingDown, true);
                    ServiceRegistration.IsShuttingDown = true;

                    UiExtension.DisposeUiServices();
                    ApplicationCore.DisposeCoreServices();

                    throw;
                }

                // Start the core
                logger.Debug("ApplicationLauncher: Starting application");

                try
                {
                    IPluginManager pluginManager = ServiceRegistration.Get <IPluginManager>();
                    pluginManager.Initialize();
                    pluginManager.Startup(false);
                    ApplicationCore.StartCoreServices();

                    ISkinEngine            skinEngine            = ServiceRegistration.Get <ISkinEngine>();
                    IWorkflowManager       workflowManager       = ServiceRegistration.Get <IWorkflowManager>();
                    IMediaAccessor         mediaAccessor         = ServiceRegistration.Get <IMediaAccessor>();
                    ILocalSharesManagement localSharesManagement = ServiceRegistration.Get <ILocalSharesManagement>();

                    // We have to handle some dependencies here in the start order:
                    // 1) After all plugins are loaded, the SkinEngine can initialize (=load all skin resources)
                    // 2) After the skin resources are loaded, the workflow manager can initialize (=load its states and actions)
                    // 3) Before the main window is shown, the splash screen should be hidden
                    // 4) After the workflow states and actions are loaded, the main window can be shown
                    // 5) After the skinengine triggers the first workflow state/startup screen, the default shortcuts can be registered
                    mediaAccessor.Initialize();         // Independent from other services
                    localSharesManagement.Initialize(); // After media accessor was initialized
                    skinEngine.Initialize();            // 1)
                    workflowManager.Initialize();       // 2)

#if !DEBUG
                    splashScreen.CloseSplashScreen(); // 3)
#endif

                    skinEngine.Startup();                                         // 4)
                    UiExtension.Startup();                                        // 5)

                    ApplicationCore.RegisterDefaultMediaItemAspectTypes().Wait(); // To be done after UI services are running

                    _ipcServer = new IpcServer("Client");
                    _ipcServer.CustomShutdownCallback = () =>
                    {
                        ServiceRegistration.Get <IScreenControl>().Shutdown();
                        return(true);
                    };
                    try
                    {
                        _ipcServer.Open();
                    }
                    catch (Exception ipcEx)
                    {
                        logger.Error(ipcEx);
                    }
                    systemStateService.SwitchSystemState(SystemState.Running, true);

                    if (mpOptions.AutoStart)
                    {
                        StartFocusKeeper();
                    }

                    Application.Run();
                    systemStateService.SwitchSystemState(SystemState.ShuttingDown, true);
                    ServiceRegistration.IsShuttingDown = true; // Block ServiceRegistration from trying to load new services in shutdown phase

                    // 1) Stop UI extensions (Releases all active players, must be done before shutting down SE)
                    // 2) Shutdown SkinEngine (Closes all screens, uninstalls background manager, stops render thread)
                    // 3) Shutdown WorkflowManager (Disposes all models)
                    // 4) Shutdown ImporterWorker
                    // 5) Shutdown PluginManager (Shuts down all plugins)
                    // 6) Remove all services
                    UiExtension.StopUiServices();
                    skinEngine.Shutdown();
                    workflowManager.Shutdown();
                    ServiceRegistration.Get <IImporterWorker>().Shutdown();
                    pluginManager.Shutdown();
                    mediaAccessor.Shutdown();
                    localSharesManagement.Shutdown();
                    ApplicationCore.StopCoreServices();
                }
                catch (Exception e)
                {
                    logger.Critical("Error executing application", e);
                    systemStateService.SwitchSystemState(SystemState.ShuttingDown, true);
                    ServiceRegistration.IsShuttingDown = true;
                }
                finally
                {
                    if (_ipcServer != null)
                    {
                        _ipcServer.Close();
                    }
                    UiExtension.DisposeUiServices();
                    ApplicationCore.DisposeCoreServices();

                    systemStateService.SwitchSystemState(SystemState.Ending, false);
                }
            }
            catch (Exception ex)
            {
#if DEBUG
                ConsoleLogger log = new ConsoleLogger(LogLevel.All, false);
                log.Error(ex);
#else
                UiCrashLogger crash = new UiCrashLogger(logPath);
                crash.CreateLog(ex);
#endif
                systemStateService.SwitchSystemState(SystemState.Ending, false);

                // Release mutex for single instance
                if (_mutex != null)
                {
                    _mutex.ReleaseMutex();
                }

                Application.Exit();
            }
        }
Beispiel #9
0
        public override void AddShare()
        {
            ILocalSharesManagement sharesManagement = ServiceRegistration.Get <ILocalSharesManagement>();

            sharesManagement.RegisterShare(ChoosenResourcePath, ShareName, MediaCategories);
        }
Beispiel #10
0
        protected internal async Task UpdateShareLists_NoLock(bool create)
        {
            lock (_syncObj)
            {
                if (_updatingProperties)
                {
                    return;
                }
                _updatingProperties = true;
                if (create)
                {
                    _serverSharesList = new ItemsList();
                    _localSharesList  = new ItemsList();
                }
            }
            try
            {
                ILocalSharesManagement sharesManagement = ServiceRegistration.Get <ILocalSharesManagement>();
                var shares = sharesManagement.Shares.Values;
                _localSharesList.Clear();
                foreach (Share share in shares)
                {
                    ListItem item = new ListItem();
                    item.SetLabel(Consts.KEY_NAME, share.Name);
                    item.AdditionalProperties[Consts.KEY_SHARE] = share;
                    if (UserProxy != null)
                    {
                        item.Selected = UserProxy.SelectedShares.Contains(share.ShareId);
                    }
                    lock (_syncObj)
                        _localSharesList.Add(item);
                }

                IServerConnectionManager scm = ServiceRegistration.Get <IServerConnectionManager>();
                if (scm == null || scm.ContentDirectory == null)
                {
                    return;
                }

                // add users to expose them
                shares = await scm.ContentDirectory.GetSharesAsync(scm.HomeServerSystemId, SharesFilter.All);

                _serverSharesList.Clear();
                foreach (Share share in shares)
                {
                    ListItem item = new ListItem();
                    item.SetLabel(Consts.KEY_NAME, share.Name);
                    item.AdditionalProperties[Consts.KEY_SHARE] = share;
                    if (UserProxy != null)
                    {
                        item.Selected = UserProxy.SelectedShares.Contains(share.ShareId);
                    }
                    lock (_syncObj)
                        _serverSharesList.Add(item);
                }
                SystemName homeServerSystem = scm.LastHomeServerSystem;
                IsLocalHomeServer     = homeServerSystem != null && homeServerSystem.IsLocalSystem();
                IsHomeServerConnected = homeServerSystem != null;
                ShowLocalShares       = !IsLocalHomeServer || _localSharesList.Count > 0;
                AnyShareAvailable     = _serverSharesList.Count > 0 || _localSharesList.Count > 0;
            }
            catch (NotConnectedException)
            {
                throw;
            }
            catch (Exception e)
            {
                ServiceRegistration.Get <ILogger>().Error("Problems updating shares", e);
            }
            finally
            {
                lock (_syncObj)
                    _updatingProperties = false;
            }
        }
Beispiel #11
0
        public override async Task <AsyncResult <ContentDirectoryMessaging.MediaItemChangeType> > ProcessAsync(MediaItem mediaItem)
        {
            // If the MediaItem was loaded from ML
            if (IsManagedByMediaLibrary(mediaItem))
            {
                IContentDirectory cd = ServiceRegistration.Get <IServerConnectionManager>().ContentDirectory;
                if (cd == null)
                {
                    return(new AsyncResult <ContentDirectoryMessaging.MediaItemChangeType>(false, ContentDirectoryMessaging.MediaItemChangeType.None));
                }

                SubtitleMatchModel misub = ServiceRegistration.Get <IWorkflowManager>().GetModel(SubtitleMatchModel.MODEL_ID_SUBMATCH) as SubtitleMatchModel;
                await misub.OpenSelectEditionDialogAsync(mediaItem).ConfigureAwait(false);

                IEnumerable <MediaItemAspect> aspects = await misub.OpenSelectMatchDialogAsync(mediaItem).ConfigureAwait(false);

                if (aspects != null)
                {
                    SubtitleInfo subtitle = new SubtitleInfo();
                    subtitle.FromMetadata(MediaItemAspect.GetAspects(aspects));

                    //Check if it is from a local share
                    bool isLocalMediaItem = false;
                    ILocalSharesManagement sharesManagement = ServiceRegistration.Get <ILocalSharesManagement>();
                    var localShares = sharesManagement.Shares.Values;
                    foreach (var media in subtitle.MediaFiles)
                    {
                        if (localShares.Any(s => s.BaseResourcePath.IsSameOrParentOf(media.NativeResourcePath)))
                        {
                            isLocalMediaItem = true;
                            break;
                        }
                    }

                    //Import directly if it is a local media item
                    if (isLocalMediaItem)
                    {
                        ServiceRegistration.Get <ILogger>().Debug("Downloading subtitle with local extractors");
                        IMediaAccessor mediaAccessor = ServiceRegistration.Get <IMediaAccessor>();
                        foreach (IMetadataExtractor extractor in mediaAccessor.LocalMetadataExtractors.Values)
                        {
                            if (!extractor.Metadata.ExtractedAspectTypes.ContainsKey(SubtitleAspect.ASPECT_ID))
                            {
                                continue;
                            }

                            await extractor.DownloadMetadataAsync(mediaItem.MediaItemId, MediaItemAspect.GetAspects(aspects)).ConfigureAwait(false);
                        }

                        foreach (var media in subtitle.MediaFiles)
                        {
                            var share = localShares.FirstOrDefault(s => s.BaseResourcePath.IsSameOrParentOf(media.NativeResourcePath));
                            if (share != null)
                            {
                                sharesManagement.ReImportShare(share.ShareId);
                                break;
                            }
                        }

                        return(new AsyncResult <ContentDirectoryMessaging.MediaItemChangeType>(true, ContentDirectoryMessaging.MediaItemChangeType.Updated));
                    }
                    else //If not get the server to import
                    {
                        ServiceRegistration.Get <ILogger>().Debug("Downloading subtitle with server extractors");
                        await cd.DownloadMetadataAsync(mediaItem.MediaItemId, aspects);

                        //After refresh is completed on server a change message will be fired
                        return(new AsyncResult <ContentDirectoryMessaging.MediaItemChangeType>(true, ContentDirectoryMessaging.MediaItemChangeType.None));
                    }
                }
            }
            return(new AsyncResult <ContentDirectoryMessaging.MediaItemChangeType>(false, ContentDirectoryMessaging.MediaItemChangeType.None));
        }
Beispiel #12
0
        /// <summary>
        /// The main entry point for the MP 2 client application.
        /// </summary>
        private static void Main(params string[] args)
        {
            Thread.CurrentThread.Name = "Main";

#if !DEBUG
            SplashScreen splashScreen = CreateSplashScreen();
            splashScreen.ShowSplashScreen();
#endif

            // Parse Command Line options
            CommandLineOptions mpArgs = new CommandLineOptions();
            ICommandLineParser parser = new CommandLineParser(new CommandLineParserSettings(Console.Error));
            if (!parser.ParseArguments(args, mpArgs, Console.Out))
            {
                Environment.Exit(1);
            }

#if !DEBUG
            string logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Team MediaPortal\MP2-Client\Log");
#endif

            SystemStateService systemStateService = new SystemStateService();
            ServiceRegistration.Set <ISystemStateService>(systemStateService);
            systemStateService.SwitchSystemState(SystemState.Initializing, false);

            try
            {
                ILogger logger = null;
                try
                {
                    // Check if user wants to override the default Application Data location.
                    ApplicationCore.RegisterCoreServices(mpArgs.DataDirectory);

                    logger = ServiceRegistration.Get <ILogger>();

#if !DEBUG
                    IPathManager pathManager = ServiceRegistration.Get <IPathManager>();
                    logPath = pathManager.GetPath("<LOG>");
#endif

                    UiExtension.RegisterUiServices();
                }
                catch (Exception e)
                {
                    if (logger != null)
                    {
                        logger.Critical("Error starting application", e);
                    }
                    systemStateService.SwitchSystemState(SystemState.ShuttingDown, true);
                    ServiceRegistration.IsShuttingDown = true;

                    UiExtension.DisposeUiServices();
                    ApplicationCore.DisposeCoreServices();

                    throw;
                }

                // Start the core
                logger.Debug("ApplicationLauncher: Starting application");

                try
                {
                    IPluginManager pluginManager = ServiceRegistration.Get <IPluginManager>();
                    pluginManager.Initialize();
                    pluginManager.Startup(false);
                    ApplicationCore.StartCoreServices();

                    ISkinEngine            skinEngine            = ServiceRegistration.Get <ISkinEngine>();
                    IWorkflowManager       workflowManager       = ServiceRegistration.Get <IWorkflowManager>();
                    IMediaAccessor         mediaAccessor         = ServiceRegistration.Get <IMediaAccessor>();
                    ILocalSharesManagement localSharesManagement = ServiceRegistration.Get <ILocalSharesManagement>();

                    // We have to handle some dependencies here in the start order:
                    // 1) After all plugins are loaded, the SkinEngine can initialize (=load all skin resources)
                    // 2) After the skin resources are loaded, the workflow manager can initialize (=load its states and actions)
                    // 3) Before the main window is shown, the splash screen should be hidden
                    // 4) After the workflow states and actions are loaded, the main window can be shown
                    // 5) After the skinengine triggers the first workflow state/startup screen, the default shortcuts can be registered
                    mediaAccessor.Initialize();         // Independent from other services
                    localSharesManagement.Initialize(); // After media accessor was initialized
                    skinEngine.Initialize();            // 1)
                    workflowManager.Initialize();       // 2)

#if !DEBUG
                    splashScreen.CloseSplashScreen(); // 3)
#endif

                    skinEngine.Startup();                                  // 4)
                    UiExtension.Startup();                                 // 5)

                    ApplicationCore.RegisterDefaultMediaItemAspectTypes(); // To be done after UI services are running

                    systemStateService.SwitchSystemState(SystemState.Running, true);

                    Application.Run();

                    systemStateService.SwitchSystemState(SystemState.ShuttingDown, true);
                    ServiceRegistration.IsShuttingDown = true; // Block ServiceRegistration from trying to load new services in shutdown phase

                    // 1) Stop UI extensions (Releases all active players, must be done before shutting down SE)
                    // 2) Shutdown SkinEngine (Closes all screens, uninstalls background manager, stops render thread)
                    // 3) Shutdown WorkflowManager (Disposes all models)
                    // 4) Shutdown PluginManager (Shuts down all plugins)
                    // 5) Remove all services
                    UiExtension.StopUiServices();
                    skinEngine.Shutdown();
                    workflowManager.Shutdown();
                    pluginManager.Shutdown();
                    mediaAccessor.Shutdown();
                    localSharesManagement.Shutdown();
                    ApplicationCore.StopCoreServices();
                }
                catch (Exception e)
                {
                    logger.Critical("Error executing application", e);
                    systemStateService.SwitchSystemState(SystemState.ShuttingDown, true);
                    ServiceRegistration.IsShuttingDown = true;
                }
                finally
                {
                    UiExtension.DisposeUiServices();
                    ApplicationCore.DisposeCoreServices();

                    systemStateService.SwitchSystemState(SystemState.Ending, false);
                }
            }
            catch (Exception ex)
            {
#if DEBUG
                ConsoleLogger log = new ConsoleLogger(LogLevel.All, false);
                log.Error(ex);
#else
                UiCrashLogger crash = new UiCrashLogger(logPath);
                crash.CreateLog(ex);
#endif
                systemStateService.SwitchSystemState(SystemState.Ending, false);
                Application.Exit();
            }
        }