diff options
58 files changed, 505 insertions, 244 deletions
diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index e552c7f1d..db768d0e8 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; +using MediaBrowser.Controller.IO; using MediaBrowser.Model.IO; using ServiceStack.ServiceHost; using System; diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 546cf4492..220101de5 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -66,14 +66,11 @@ <Reference Include="System" /> <Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.Core" /> - <Reference Include="System.Deployment" /> <Reference Include="System.Drawing" /> <Reference Include="System.Runtime.Serialization" /> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="Microsoft.CSharp" /> <Reference Include="System.Data" /> - <Reference Include="System.Xml" /> + <Reference Include="System.XML" /> </ItemGroup> <ItemGroup> <Compile Include="ApiService.cs" /> @@ -87,6 +84,8 @@ <Compile Include="LocalizationService.cs" /> <Compile Include="PackageService.cs" /> <Compile Include="PluginService.cs" /> + <Compile Include="ScheduledTasks\ScheduledTaskService.cs" /> + <Compile Include="ScheduledTasks\ScheduledTasksWebSocketListener.cs" /> <Compile Include="SystemService.cs" /> <Compile Include="Streaming\AudioHandler.cs" /> <Compile Include="Streaming\BaseHlsPlaylistHandler.cs" /> @@ -108,6 +107,8 @@ <Compile Include="Plugin.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="WeatherService.cs" /> + <Compile Include="WebSocket\LogFileWebSocketListener.cs" /> + <Compile Include="WebSocket\SystemInfoWebSocketListener.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs index 64c5d6cbc..924c33937 100644 --- a/MediaBrowser.Api/PackageService.cs +++ b/MediaBrowser.Api/PackageService.cs @@ -1,8 +1,7 @@ using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Kernel; using MediaBrowser.Common.Net; -using MediaBrowser.Common.Updates; using MediaBrowser.Controller; -using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Updates; using ServiceStack.ServiceHost; using System; @@ -98,6 +97,12 @@ namespace MediaBrowser.Api public class PackageService : BaseRestService { /// <summary> + /// Gets or sets the application host. + /// </summary> + /// <value>The application host.</value> + public IApplicationHost ApplicationHost { get; set; } + + /// <summary> /// Gets the specified request. /// </summary> /// <param name="request">The request.</param> @@ -116,9 +121,9 @@ namespace MediaBrowser.Api else if (request.PackageType == PackageType.System || request.PackageType == PackageType.All) { - var updateCheckResult = new ApplicationUpdateCheck().CheckForApplicationUpdate(CancellationToken.None, new Progress<TaskProgress> { }).Result; + var updateCheckResult = ApplicationHost.CheckForApplicationUpdate(CancellationToken.None, new Progress<double> { }).Result; - if (updateCheckResult.UpdateAvailable) + if (updateCheckResult.IsUpdateAvailable) { result.Add(new PackageVersionInfo { diff --git a/MediaBrowser.Common/Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs index 1df24dcd2..bd12454a0 100644 --- a/MediaBrowser.Common/Api/ScheduledTasks/ScheduledTaskService.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs @@ -11,7 +11,7 @@ using System.IO; using System.Linq; using ServiceStack.Text.Controller; -namespace MediaBrowser.Common.Api.ScheduledTasks +namespace MediaBrowser.Api.ScheduledTasks { /// <summary> /// Class GetScheduledTask diff --git a/MediaBrowser.Common/Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs index 7e4596d9d..7fa47735e 100644 --- a/MediaBrowser.Common/Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs @@ -7,7 +7,7 @@ using System.ComponentModel.Composition; using System.Linq; using System.Threading.Tasks; -namespace MediaBrowser.Common.Api.ScheduledTasks +namespace MediaBrowser.Api.ScheduledTasks { /// <summary> /// Class ScheduledTasksWebSocketListener diff --git a/MediaBrowser.Common/Api/Logging/LogFileWebSocketListener.cs b/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs index e873facb1..f725b0222 100644 --- a/MediaBrowser.Common/Api/Logging/LogFileWebSocketListener.cs +++ b/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs @@ -8,7 +8,7 @@ using System.Linq; using System.Threading.Tasks; using MediaBrowser.Model.Logging; -namespace MediaBrowser.Common.Api.Logging +namespace MediaBrowser.Api.WebSocket { /// <summary> /// Class ScheduledTasksWebSocketListener diff --git a/MediaBrowser.Common/Api/SystemInfoWebSocketListener.cs b/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs index a216937ed..51d9f2fcd 100644 --- a/MediaBrowser.Common/Api/SystemInfoWebSocketListener.cs +++ b/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs @@ -1,15 +1,16 @@ using MediaBrowser.Common.Kernel; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.System; using System.ComponentModel.Composition; using System.Threading.Tasks; -namespace MediaBrowser.Common.Api +namespace MediaBrowser.Api.WebSocket { /// <summary> /// Class SystemInfoWebSocketListener /// </summary> [Export(typeof(IWebSocketListener))] - public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener<IKernel, Model.System.SystemInfo, object> + public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener<IKernel, SystemInfo, object> { /// <summary> /// Gets the name. @@ -36,7 +37,7 @@ namespace MediaBrowser.Common.Api /// </summary> /// <param name="state">The state.</param> /// <returns>Task{SystemInfo}.</returns> - protected override Task<Model.System.SystemInfo> GetDataToSend(object state) + protected override Task<SystemInfo> GetDataToSend(object state) { return Task.FromResult(Kernel.GetSystemInfo()); } diff --git a/MediaBrowser.Common/Updates/ApplicationUpdateCheck.cs b/MediaBrowser.ClickOnce/ApplicationUpdateCheck.cs index 7501d7321..72c42f586 100644 --- a/MediaBrowser.Common/Updates/ApplicationUpdateCheck.cs +++ b/MediaBrowser.ClickOnce/ApplicationUpdateCheck.cs @@ -1,10 +1,10 @@ -using MediaBrowser.Model.Tasks; +using MediaBrowser.Model.Updates; using System; using System.Deployment.Application; using System.Threading; using System.Threading.Tasks; -namespace MediaBrowser.Common.Updates +namespace MediaBrowser.ClickOnce { /// <summary> /// Class ApplicationUpdateCheck @@ -14,12 +14,12 @@ namespace MediaBrowser.Common.Updates /// <summary> /// The _task completion source /// </summary> - private TaskCompletionSource<CheckForUpdateCompletedEventArgs> _taskCompletionSource; + private TaskCompletionSource<CheckForUpdateResult> _taskCompletionSource; /// <summary> /// The _progress /// </summary> - private IProgress<TaskProgress> _progress; + private IProgress<double> _progress; /// <summary> /// Checks for application update. @@ -28,7 +28,7 @@ namespace MediaBrowser.Common.Updates /// <param name="progress">The progress.</param> /// <returns>Task{CheckForUpdateCompletedEventArgs}.</returns> /// <exception cref="System.InvalidOperationException">Current deployment is not a ClickOnce deployment</exception> - public Task<CheckForUpdateCompletedEventArgs> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + public Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress) { if (!ApplicationDeployment.IsNetworkDeployed) { @@ -36,8 +36,8 @@ namespace MediaBrowser.Common.Updates } _progress = progress; - - _taskCompletionSource = new TaskCompletionSource<CheckForUpdateCompletedEventArgs>(); + + _taskCompletionSource = new TaskCompletionSource<CheckForUpdateResult>(); var deployment = ApplicationDeployment.CurrentDeployment; @@ -54,6 +54,20 @@ namespace MediaBrowser.Common.Updates } /// <summary> + /// To the result. + /// </summary> + /// <param name="args">The <see cref="CheckForUpdateCompletedEventArgs" /> instance containing the event data.</param> + /// <returns>CheckForUpdateResult.</returns> + private CheckForUpdateResult ToResult(CheckForUpdateCompletedEventArgs args) + { + return new CheckForUpdateResult + { + AvailableVersion = args.AvailableVersion, + IsUpdateAvailable = args.UpdateAvailable + }; + } + + /// <summary> /// Handles the CheckForUpdateCompleted event of the deployment control. /// </summary> /// <param name="sender">The source of the event.</param> @@ -75,7 +89,7 @@ namespace MediaBrowser.Common.Updates } else { - _taskCompletionSource.SetResult(e); + _taskCompletionSource.SetResult(ToResult(e)); } } @@ -86,7 +100,7 @@ namespace MediaBrowser.Common.Updates /// <param name="e">The <see cref="DeploymentProgressChangedEventArgs" /> instance containing the event data.</param> void deployment_CheckForUpdateProgressChanged(object sender, DeploymentProgressChangedEventArgs e) { - _progress.Report(new TaskProgress { PercentComplete = e.ProgressPercentage }); + _progress.Report(e.ProgressPercentage); } } } diff --git a/MediaBrowser.Common/Updates/ApplicationUpdater.cs b/MediaBrowser.ClickOnce/ApplicationUpdater.cs index d8ae87b37..29af406f1 100644 --- a/MediaBrowser.Common/Updates/ApplicationUpdater.cs +++ b/MediaBrowser.ClickOnce/ApplicationUpdater.cs @@ -1,11 +1,10 @@ -using MediaBrowser.Model.Tasks; -using System; +using System; using System.ComponentModel; using System.Deployment.Application; using System.Threading; using System.Threading.Tasks; -namespace MediaBrowser.Common.Updates +namespace MediaBrowser.ClickOnce { /// <summary> /// Class ApplicationUpdater @@ -20,7 +19,7 @@ namespace MediaBrowser.Common.Updates /// <summary> /// The _progress /// </summary> - private IProgress<TaskProgress> _progress; + private IProgress<double> _progress; /// <summary> /// Updates the application @@ -29,7 +28,7 @@ namespace MediaBrowser.Common.Updates /// <param name="progress">The progress.</param> /// <returns>Task{AsyncCompletedEventArgs}.</returns> /// <exception cref="System.InvalidOperationException">Current deployment is not network deployed.</exception> - public Task<AsyncCompletedEventArgs> UpdateApplication(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + public Task<AsyncCompletedEventArgs> UpdateApplication(CancellationToken cancellationToken, IProgress<double> progress) { if (!ApplicationDeployment.IsNetworkDeployed) { @@ -87,7 +86,7 @@ namespace MediaBrowser.Common.Updates /// <param name="e">The <see cref="DeploymentProgressChangedEventArgs" /> instance containing the event data.</param> void deployment_UpdateProgressChanged(object sender, DeploymentProgressChangedEventArgs e) { - _progress.Report(new TaskProgress { PercentComplete = e.ProgressPercentage }); + _progress.Report(e.ProgressPercentage); } } } diff --git a/MediaBrowser.Common/Updates/ClickOnceHelper.cs b/MediaBrowser.ClickOnce/ClickOnceHelper.cs index 7dd0cf9c5..c86332ccf 100644 --- a/MediaBrowser.Common/Updates/ClickOnceHelper.cs +++ b/MediaBrowser.ClickOnce/ClickOnceHelper.cs @@ -1,4 +1,5 @@ -using Microsoft.Win32; +using System.Deployment.Application; +using Microsoft.Win32; using System; using System.Diagnostics; using System.IO; @@ -6,7 +7,7 @@ using System.Linq; using System.Reflection; using System.Security.AccessControl; -namespace MediaBrowser.Common.Updates +namespace MediaBrowser.ClickOnce { /// <summary> /// Class ClickOnceHelper @@ -44,6 +45,15 @@ namespace MediaBrowser.Common.Updates } /// <summary> + /// Gets a value indicating whether this instance is network deployed. + /// </summary> + /// <value><c>true</c> if this instance is network deployed; otherwise, <c>false</c>.</value> + public static bool IsNetworkDeployed + { + get { return ApplicationDeployment.IsNetworkDeployed; } + } + + /// <summary> /// Gets the name of the publisher. /// </summary> /// <value>The name of the publisher.</value> @@ -213,5 +223,33 @@ namespace MediaBrowser.Common.Updates }.Start(); } + + /// <summary> + /// Configures the click once startup. + /// </summary> + /// <param name="publisherName">Name of the publisher.</param> + /// <param name="productName">Name of the product.</param> + /// <param name="suiteName">Name of the suite.</param> + /// <param name="runAtStartup">if set to <c>true</c> [run at startup].</param> + /// <param name="uninstallerFilename">The uninstaller filename.</param> + public static void ConfigureClickOnceStartupIfInstalled(string publisherName, string productName, string suiteName, bool runAtStartup, string uninstallerFilename) + { + if (!ApplicationDeployment.IsNetworkDeployed) + { + return; + } + + var clickOnceHelper = new ClickOnceHelper(publisherName, productName, suiteName); + + if (runAtStartup) + { + clickOnceHelper.UpdateUninstallParameters(uninstallerFilename); + clickOnceHelper.AddShortcutToStartup(); + } + else + { + clickOnceHelper.RemoveShortcutFromStartup(); + } + } } } diff --git a/MediaBrowser.ClickOnce/MediaBrowser.ClickOnce.csproj b/MediaBrowser.ClickOnce/MediaBrowser.ClickOnce.csproj new file mode 100644 index 000000000..00370bfcd --- /dev/null +++ b/MediaBrowser.ClickOnce/MediaBrowser.ClickOnce.csproj @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>MediaBrowser.ClickOnce</RootNamespace> + <AssemblyName>MediaBrowser.ClickOnce</AssemblyName> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Deployment" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="ApplicationUpdateCheck.cs" /> + <Compile Include="ApplicationUpdater.cs" /> + <Compile Include="ClickOnceHelper.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj"> + <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project> + <Name>MediaBrowser.Model</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/MediaBrowser.ClickOnce/Properties/AssemblyInfo.cs b/MediaBrowser.ClickOnce/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..1faa44e01 --- /dev/null +++ b/MediaBrowser.ClickOnce/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MediaBrowser.ClickOnce")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MediaBrowser.ClickOnce")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("16e62c11-5009-4212-8c96-fd692479fc5d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MediaBrowser.Common/Extensions/BaseExtensions.cs b/MediaBrowser.Common/Extensions/BaseExtensions.cs index e6b9d8ee6..6abe6d4e0 100644 --- a/MediaBrowser.Common/Extensions/BaseExtensions.cs +++ b/MediaBrowser.Common/Extensions/BaseExtensions.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; -using System.Windows.Threading; namespace MediaBrowser.Common.Extensions { @@ -47,24 +46,6 @@ namespace MediaBrowser.Common.Extensions } /// <summary> - /// Invokes an action after a specified delay - /// </summary> - /// <param name="dispatcher">The dispatcher.</param> - /// <param name="action">The action.</param> - /// <param name="delayMs">The delay ms.</param> - public static void InvokeWithDelay(this Dispatcher dispatcher, Action action, long delayMs) - { - var timer = new DispatcherTimer(DispatcherPriority.Normal, dispatcher); - timer.Interval = TimeSpan.FromMilliseconds(delayMs); - timer.Tick += (sender, args) => - { - timer.Stop(); - action(); - }; - timer.Start(); - } - - /// <summary> /// Provides a non-blocking method to start a process and wait asynchronously for it to exit /// </summary> /// <param name="process">The process.</param> diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index a4ac70749..d172d0a0d 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -13,7 +13,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; -using System.Deployment.Application; using System.Diagnostics; using System.IO; using System.Linq; @@ -156,12 +155,6 @@ namespace MediaBrowser.Common.Kernel public bool IsFirstRun { get; private set; } /// <summary> - /// The version of the application to display - /// </summary> - /// <value>The display version.</value> - public string DisplayVersion { get { return ApplicationVersion.ToString(); } } - - /// <summary> /// Gets or sets a value indicating whether this instance has changes that require the entire application to restart. /// </summary> /// <value><c>true</c> if this instance has pending application restart; otherwise, <c>false</c>.</value> @@ -325,7 +318,10 @@ namespace MediaBrowser.Common.Kernel /// Gets the log file path. /// </summary> /// <value>The log file path.</value> - public string LogFilePath { get; private set; } + public string LogFilePath + { + get { return ApplicationHost.LogFilePath; } + } /// <summary> /// Gets the logger. @@ -429,7 +425,7 @@ namespace MediaBrowser.Common.Kernel await ReloadComposableParts().ConfigureAwait(false); DisposeTcpManager(); - TcpManager = new TcpManager(this, Logger); + TcpManager = new TcpManager(ApplicationHost, this, Logger); } /// <summary> @@ -482,6 +478,7 @@ namespace MediaBrowser.Common.Kernel protected virtual void ComposeExportedValues(CompositionContainer container) { container.ComposeExportedValue("logger", Logger); + container.ComposeExportedValue("appHost", ApplicationHost); } /// <summary> @@ -729,8 +726,8 @@ namespace MediaBrowser.Common.Kernel return new SystemInfo { HasPendingRestart = HasPendingRestart, - Version = DisplayVersion, - IsNetworkDeployed = ApplicationDeployment.IsNetworkDeployed, + Version = ApplicationVersion.ToString(), + IsNetworkDeployed = ApplicationHost.CanSelfUpdate, WebSocketPortNumber = TcpManager.WebSocketPortNumber, SupportsNativeWebSocket = TcpManager.SupportsNativeWebSocket, FailedPluginAssemblies = FailedPluginAssemblies.ToArray() diff --git a/MediaBrowser.Common/Kernel/IApplicationHost.cs b/MediaBrowser.Common/Kernel/IApplicationHost.cs index c1b63c261..63c63eb3d 100644 --- a/MediaBrowser.Common/Kernel/IApplicationHost.cs +++ b/MediaBrowser.Common/Kernel/IApplicationHost.cs @@ -1,4 +1,8 @@ - +using MediaBrowser.Model.Updates; +using System; +using System.Threading; +using System.Threading.Tasks; + namespace MediaBrowser.Common.Kernel { /// <summary> @@ -15,5 +19,29 @@ namespace MediaBrowser.Common.Kernel /// Reloads the logger. /// </summary> void ReloadLogger(); + + /// <summary> + /// Gets the log file path. + /// </summary> + /// <value>The log file path.</value> + string LogFilePath { get; } + + /// <summary> + /// Gets or sets a value indicating whether this instance can self update. + /// </summary> + /// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value> + bool CanSelfUpdate { get; } + + /// <summary> + /// Checks for update. + /// </summary> + /// <returns>Task{CheckForUpdateResult}.</returns> + Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress); + + /// <summary> + /// Updates the application. + /// </summary> + /// <returns>Task.</returns> + Task UpdateApplication(CancellationToken cancellationToken, IProgress<double> progress); } } diff --git a/MediaBrowser.Common/Kernel/TcpManager.cs b/MediaBrowser.Common/Kernel/TcpManager.cs index 7fb624f73..086815cbf 100644 --- a/MediaBrowser.Common/Kernel/TcpManager.cs +++ b/MediaBrowser.Common/Kernel/TcpManager.cs @@ -64,6 +64,11 @@ namespace MediaBrowser.Common.Kernel /// The _logger /// </summary> private readonly ILogger _logger; + + /// <summary> + /// The _application host + /// </summary> + private readonly IApplicationHost _applicationHost; /// <summary> /// The _supports native web socket @@ -108,12 +113,14 @@ namespace MediaBrowser.Common.Kernel /// <summary> /// Initializes a new instance of the <see cref="TcpManager" /> class. /// </summary> + /// <param name="applicationHost">The application host.</param> /// <param name="kernel">The kernel.</param> /// <param name="logger">The logger.</param> - public TcpManager(IKernel kernel, ILogger logger) + public TcpManager(IApplicationHost applicationHost, IKernel kernel, ILogger logger) : base(kernel) { _logger = logger; + _applicationHost = applicationHost; if (kernel.IsFirstRun) { @@ -182,7 +189,7 @@ namespace MediaBrowser.Common.Kernel try { - HttpServer = new HttpServer(Kernel.HttpServerUrlPrefix, "Media Browser", Kernel, _logger); + HttpServer = new HttpServer(Kernel.HttpServerUrlPrefix, "Media Browser", _applicationHost, Kernel, _logger); } catch (HttpListenerException ex) { diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index b806df856..c7b162dee 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -34,7 +34,8 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <PropertyGroup> - <ApplicationIcon>Resources\Images\Icon.ico</ApplicationIcon> + <ApplicationIcon> + </ApplicationIcon> </PropertyGroup> <ItemGroup> <Reference Include="Alchemy"> @@ -94,7 +95,6 @@ <Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.Configuration" /> <Reference Include="System.Core" /> - <Reference Include="System.Deployment" /> <Reference Include="System.Management" /> <Reference Include="System.Net" /> <Reference Include="System.Net.Http" /> @@ -118,13 +118,8 @@ <Reference Include="Microsoft.CSharp" /> <Reference Include="System.Data" /> <Reference Include="System.Xml" /> - <Reference Include="WindowsBase" /> </ItemGroup> <ItemGroup> - <Compile Include="Api\Logging\LogFileWebSocketListener.cs" /> - <Compile Include="Api\ScheduledTasks\ScheduledTaskService.cs" /> - <Compile Include="Api\ScheduledTasks\ScheduledTasksWebSocketListener.cs" /> - <Compile Include="Api\SystemInfoWebSocketListener.cs" /> <Compile Include="Events\EventHelper.cs" /> <Compile Include="Extensions\BaseExtensions.cs" /> <Compile Include="Events\GenericEventArgs.cs" /> @@ -156,8 +151,6 @@ <Compile Include="Net\MimeTypes.cs" /> <Compile Include="Net\NativeWebSocket.cs" /> <Compile Include="Net\NetUtils.cs" /> - <Compile Include="Net\NetworkShares.cs" /> - <Compile Include="Net\StaticResult.cs" /> <Compile Include="Net\UdpServer.cs" /> <Compile Include="Net\WebSocketConnection.cs" /> <Compile Include="Plugins\BaseUiPlugin.cs" /> @@ -193,9 +186,6 @@ <Compile Include="ScheduledTasks\IntervalTrigger.cs" /> <Compile Include="ScheduledTasks\IScheduledTask.cs" /> <Compile Include="ScheduledTasks\WeeklyTrigger.cs" /> - <Compile Include="Updates\ApplicationUpdateCheck.cs" /> - <Compile Include="Updates\ApplicationUpdater.cs" /> - <Compile Include="Updates\ClickOnceHelper.cs" /> <Compile Include="Win32\NativeMethods.cs" /> </ItemGroup> <ItemGroup> @@ -217,9 +207,6 @@ </EmbeddedResource> </ItemGroup> <ItemGroup> - <Resource Include="Resources\Images\Icon.ico" /> - </ItemGroup> - <ItemGroup> <Resource Include="README.txt" /> <Content Include="swagger-ui\css\screen.css" /> <Resource Include="swagger-ui\images\pet_store_api.png" /> diff --git a/MediaBrowser.Common/Net/HttpServer.cs b/MediaBrowser.Common/Net/HttpServer.cs index 184b82c16..b09c95da0 100644 --- a/MediaBrowser.Common/Net/HttpServer.cs +++ b/MediaBrowser.Common/Net/HttpServer.cs @@ -46,6 +46,12 @@ namespace MediaBrowser.Common.Net private IKernel Kernel { get; set; } /// <summary> + /// Gets or sets the application host. + /// </summary> + /// <value>The application host.</value> + private IApplicationHost ApplicationHost { get; set; } + + /// <summary> /// This subscribes to HttpListener requests and finds the appropriate BaseHandler to process it /// </summary> /// <value>The HTTP listener.</value> @@ -67,11 +73,12 @@ namespace MediaBrowser.Common.Net /// </summary> /// <param name="urlPrefix">The URL.</param> /// <param name="serverName">Name of the product.</param> + /// <param name="applicationHost">The application host.</param> /// <param name="kernel">The kernel.</param> /// <param name="logger">The logger.</param> /// <param name="defaultRedirectpath">The default redirectpath.</param> /// <exception cref="System.ArgumentNullException">urlPrefix</exception> - public HttpServer(string urlPrefix, string serverName, IKernel kernel, ILogger logger, string defaultRedirectpath = null) + public HttpServer(string urlPrefix, string serverName, IApplicationHost applicationHost, IKernel kernel, ILogger logger, string defaultRedirectpath = null) : base() { if (string.IsNullOrEmpty(urlPrefix)) @@ -86,9 +93,14 @@ namespace MediaBrowser.Common.Net { throw new ArgumentNullException("logger"); } + if (applicationHost == null) + { + throw new ArgumentNullException("applicationHost"); + } DefaultRedirectPath = defaultRedirectpath; _logger = logger; + ApplicationHost = applicationHost; EndpointHostConfig.Instance.ServiceStackHandlerFactoryPath = null; EndpointHostConfig.Instance.MetadataRedirectPath = "metadata"; @@ -144,6 +156,7 @@ namespace MediaBrowser.Common.Net container.Register(Kernel); container.Register(_logger); + container.Register(ApplicationHost); foreach (var service in Kernel.RestServices) { diff --git a/MediaBrowser.Common/Net/StaticResult.cs b/MediaBrowser.Common/Net/StaticResult.cs deleted file mode 100644 index 0dd6372cf..000000000 --- a/MediaBrowser.Common/Net/StaticResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.Net -{ - public class StaticResult - { - public Stream Stream { get; set; } - } -} diff --git a/MediaBrowser.Common/Resources/Images/Icon.ico b/MediaBrowser.Common/Resources/Images/Icon.ico Binary files differdeleted file mode 100644 index bea939de4..000000000 --- a/MediaBrowser.Common/Resources/Images/Icon.ico +++ /dev/null diff --git a/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs index 99dd7ab01..395c73a84 100644 --- a/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs @@ -171,7 +171,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// Gets the current progress. /// </summary> /// <value>The current progress.</value> - public TaskProgress CurrentProgress { get; private set; } + public double? CurrentProgress { get; private set; } /// <summary> /// The _triggers @@ -246,7 +246,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected abstract Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress); + protected abstract Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress); /// <summary> /// Gets the name of the task @@ -355,7 +355,7 @@ namespace MediaBrowser.Common.ScheduledTasks Logger.Info("Executing {0}", Name); - var progress = new Progress<TaskProgress>(); + var progress = new Progress<double>(); progress.ProgressChanged += progress_ProgressChanged; @@ -426,7 +426,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> - void progress_ProgressChanged(object sender, TaskProgress e) + void progress_ProgressChanged(object sender, double e) { CurrentProgress = e; } diff --git a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs index a3809c4b9..95d1edf63 100644 --- a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// Gets the current progress. /// </summary> /// <value>The current progress.</value> - TaskProgress CurrentProgress { get; } + double? CurrentProgress { get; } /// <summary> /// Gets the name of the task diff --git a/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs b/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs index 34421ca1f..95c4c6a66 100644 --- a/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs +++ b/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Common.ScheduledTasks return new TaskInfo { Name = task.Name, - CurrentProgress = task.CurrentProgress, + CurrentProgressPercentage = task.CurrentProgress, State = task.State, Id = task.Id, LastExecutionResult = task.LastExecutionResult, diff --git a/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index 98c6d672a..2a9bc4a0d 100644 --- a/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) { return Task.Run(() => { @@ -51,7 +51,7 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks /// <param name="directory">The directory.</param> /// <param name="minDateModified">The min date modified.</param> /// <param name="progress">The progress.</param> - private void DeleteCacheFilesFromDirectory(CancellationToken cancellationToken, string directory, DateTime minDateModified, IProgress<TaskProgress> progress) + private void DeleteCacheFilesFromDirectory(CancellationToken cancellationToken, string directory, DateTime minDateModified, IProgress<double> progress) { var filesToDelete = new DirectoryInfo(directory).EnumerateFileSystemInfos("*", SearchOption.AllDirectories) .Where(f => !f.Attributes.HasFlag(FileAttributes.Directory) && f.LastWriteTimeUtc < minDateModified) @@ -64,7 +64,7 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks double percent = index; percent /= filesToDelete.Count; - progress.Report(new TaskProgress { Description = file.FullName, PercentComplete = 100 * percent }); + progress.Report(100 * percent); cancellationToken.ThrowIfCancellationRequested(); @@ -73,7 +73,7 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks index++; } - progress.Report(new TaskProgress { PercentComplete = 100 }); + progress.Report(100); } /// <summary> diff --git a/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteLogFileTask.cs index afb21187c..a1068a263 100644 --- a/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteLogFileTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/Tasks/DeleteLogFileTask.cs @@ -33,7 +33,7 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) { return Task.Run(() => { @@ -51,7 +51,7 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks double percent = index; percent /= filesToDelete.Count; - progress.Report(new TaskProgress { Description = file.FullName, PercentComplete = 100 * percent }); + progress.Report(100 * percent); cancellationToken.ThrowIfCancellationRequested(); @@ -60,7 +60,7 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks index++; } - progress.Report(new TaskProgress { PercentComplete = 100 }); + progress.Report(100); }); } diff --git a/MediaBrowser.Common/ScheduledTasks/Tasks/ReloadLoggerTask.cs b/MediaBrowser.Common/ScheduledTasks/Tasks/ReloadLoggerTask.cs index 24aaad57f..a4f06f205 100644 --- a/MediaBrowser.Common/ScheduledTasks/Tasks/ReloadLoggerTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/Tasks/ReloadLoggerTask.cs @@ -31,11 +31,11 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) { cancellationToken.ThrowIfCancellationRequested(); - progress.Report(new TaskProgress { PercentComplete = 0 }); + progress.Report(0); return Task.Run(() => Kernel.ReloadLogger()); } diff --git a/MediaBrowser.Common/ScheduledTasks/Tasks/SystemUpdateTask.cs b/MediaBrowser.Common/ScheduledTasks/Tasks/SystemUpdateTask.cs index a7e3f90a0..f9950424f 100644 --- a/MediaBrowser.Common/ScheduledTasks/Tasks/SystemUpdateTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/Tasks/SystemUpdateTask.cs @@ -1,10 +1,7 @@ using MediaBrowser.Common.Kernel; -using MediaBrowser.Common.Updates; -using MediaBrowser.Model.Tasks; using System; using System.Collections.Generic; using System.ComponentModel.Composition; -using System.Deployment.Application; using System.Threading; using System.Threading.Tasks; @@ -17,6 +14,21 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks public class SystemUpdateTask : BaseScheduledTask<IKernel> { /// <summary> + /// The _app host + /// </summary> + private readonly IApplicationHost _appHost; + + /// <summary> + /// Initializes a new instance of the <see cref="SystemUpdateTask" /> class. + /// </summary> + /// <param name="appHost">The app host.</param> + [ImportingConstructor] + public SystemUpdateTask([Import("appHost")] IApplicationHost appHost) + { + _appHost = appHost; + } + + /// <summary> /// Creates the triggers that define when the task will run /// </summary> /// <returns>IEnumerable{BaseTaskTrigger}.</returns> @@ -37,26 +49,26 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected override async Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + protected override async Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) { - if (!ApplicationDeployment.IsNetworkDeployed) return; + if (!_appHost.CanSelfUpdate) return; - EventHandler<TaskProgress> innerProgressHandler = (sender, e) => progress.Report(new TaskProgress { PercentComplete = e.PercentComplete * .1 }); + EventHandler<double> innerProgressHandler = (sender, e) => progress.Report(e * .1); // Create a progress object for the update check - var innerProgress = new Progress<TaskProgress>(); + var innerProgress = new Progress<double>(); innerProgress.ProgressChanged += innerProgressHandler; - var updateInfo = await new ApplicationUpdateCheck().CheckForApplicationUpdate(cancellationToken, innerProgress).ConfigureAwait(false); + var updateInfo = await _appHost.CheckForApplicationUpdate(cancellationToken, innerProgress).ConfigureAwait(false); // Release the event handler innerProgress.ProgressChanged -= innerProgressHandler; - progress.Report(new TaskProgress { PercentComplete = 10 }); + progress.Report(10); - if (!updateInfo.UpdateAvailable) + if (!updateInfo.IsUpdateAvailable) { - progress.Report(new TaskProgress { PercentComplete = 100 }); + progress.Report(100); return; } @@ -66,12 +78,12 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks { Logger.Info("Update Revision {0} available. Updating...", updateInfo.AvailableVersion); - innerProgressHandler = (sender, e) => progress.Report(new TaskProgress { PercentComplete = (e.PercentComplete * .9) + .1 }); + innerProgressHandler = (sender, e) => progress.Report((e * .9) + .1); - innerProgress = new Progress<TaskProgress>(); + innerProgress = new Progress<double>(); innerProgress.ProgressChanged += innerProgressHandler; - await new ApplicationUpdater().UpdateApplication(cancellationToken, innerProgress).ConfigureAwait(false); + await _appHost.UpdateApplication(cancellationToken, innerProgress).ConfigureAwait(false); // Release the event handler innerProgress.ProgressChanged -= innerProgressHandler; @@ -83,7 +95,7 @@ namespace MediaBrowser.Common.ScheduledTasks.Tasks Logger.Info("A new version of Media Browser is available."); } - progress.Report(new TaskProgress { PercentComplete = 100 }); + progress.Report(100); } /// <summary> diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 33e9f291d..fbcd2f589 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -56,7 +56,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="cancellationToken">The cancellation token.</param> /// <param name="recursive">if set to <c>true</c> [recursive].</param> /// <returns>Task.</returns> - protected override Task ValidateChildrenInternal(IProgress<TaskProgress> progress, CancellationToken cancellationToken, bool? recursive = null) + protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool? recursive = null) { //we don't directly validate our children //but we do need to clear out the index cache... diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index f67934f5d..bcb0b26be 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -612,7 +612,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="cancellationToken">The cancellation token.</param> /// <param name="recursive">if set to <c>true</c> [recursive].</param> /// <returns>Task.</returns> - public async Task ValidateChildren(IProgress<TaskProgress> progress, CancellationToken cancellationToken, bool? recursive = null) + public async Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken, bool? recursive = null) { cancellationToken.ThrowIfCancellationRequested(); @@ -664,7 +664,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="cancellationToken">The cancellation token.</param> /// <param name="recursive">if set to <c>true</c> [recursive].</param> /// <returns>Task.</returns> - protected async virtual Task ValidateChildrenInternal(IProgress<TaskProgress> progress, CancellationToken cancellationToken, bool? recursive = null) + protected async virtual Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool? recursive = null) { // Nothing to do here if (LocationType != LocationType.FileSystem) @@ -681,7 +681,7 @@ namespace MediaBrowser.Controller.Entities if (nonCachedChildren == null) return; //nothing to validate - progress.Report(new TaskProgress { PercentComplete = 5 }); + progress.Report(5); //build a dictionary of the current children we have now by Id so we can compare quickly and easily var currentChildren = ActualChildren.ToDictionary(i => i.Id); @@ -772,13 +772,13 @@ namespace MediaBrowser.Controller.Entities Kernel.Instance.LibraryManager.OnLibraryChanged(changedArgs); } - progress.Report(new TaskProgress { PercentComplete = 15 }); + progress.Report(15); cancellationToken.ThrowIfCancellationRequested(); await RefreshChildren(validChildren, progress, cancellationToken, recursive).ConfigureAwait(false); - progress.Report(new TaskProgress { PercentComplete = 100 }); + progress.Report(100); } /// <summary> @@ -789,7 +789,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="cancellationToken">The cancellation token.</param> /// <param name="recursive">if set to <c>true</c> [recursive].</param> /// <returns>Task.</returns> - private Task RefreshChildren(IEnumerable<Tuple<BaseItem, bool>> children, IProgress<TaskProgress> progress, CancellationToken cancellationToken, bool? recursive) + private Task RefreshChildren(IEnumerable<Tuple<BaseItem, bool>> children, IProgress<double> progress, CancellationToken cancellationToken, bool? recursive) { var numComplete = 0; @@ -824,7 +824,7 @@ namespace MediaBrowser.Controller.Entities { cancellationToken.ThrowIfCancellationRequested(); - await ((Folder)child).ValidateChildren(new Progress<TaskProgress> { }, cancellationToken, recursive: recursive).ConfigureAwait(false); + await ((Folder)child).ValidateChildren(new Progress<double> { }, cancellationToken, recursive: recursive).ConfigureAwait(false); } lock (progress) @@ -834,7 +834,7 @@ namespace MediaBrowser.Controller.Entities double percent = numComplete; percent /= list.Count; - progress.Report(new TaskProgress { PercentComplete = (85 * percent) + 15 }); + progress.Report((85 * percent) + 15); } })); @@ -952,7 +952,7 @@ namespace MediaBrowser.Controller.Entities { await base.ChangedExternally().ConfigureAwait(false); - var progress = new Progress<TaskProgress> { }; + var progress = new Progress<double> { }; await ValidateChildren(progress, CancellationToken.None).ConfigureAwait(false); } diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index ee9815e62..f27e8c689 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -205,7 +205,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - public async Task ValidateMediaLibrary(IProgress<TaskProgress> progress, CancellationToken cancellationToken) + public async Task ValidateMediaLibrary(IProgress<double> progress, CancellationToken cancellationToken) { Logger.Info("Validating media library for {0}", Name); await RootFolder.RefreshMetadata(cancellationToken).ConfigureAwait(false); @@ -221,7 +221,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - public async Task ValidateCollectionFolders(IProgress<TaskProgress> progress, CancellationToken cancellationToken) + public async Task ValidateCollectionFolders(IProgress<double> progress, CancellationToken cancellationToken) { Logger.Info("Validating collection folders for {0}", Name); await RootFolder.RefreshMetadata(cancellationToken).ConfigureAwait(false); @@ -279,7 +279,7 @@ namespace MediaBrowser.Controller.Entities RootFolder = null; // Kick off a task to validate the media library - Task.Run(() => ValidateMediaLibrary(new Progress<TaskProgress> { }, CancellationToken.None)); + Task.Run(() => ValidateMediaLibrary(new Progress<double> { }, CancellationToken.None)); return RefreshMetadata(CancellationToken.None, forceSave: true, forceRefresh: true); } diff --git a/MediaBrowser.Common/Net/NetworkShares.cs b/MediaBrowser.Controller/IO/NetworkShares.cs index 202865b4c..93edc6447 100644 --- a/MediaBrowser.Common/Net/NetworkShares.cs +++ b/MediaBrowser.Controller/IO/NetworkShares.cs @@ -3,7 +3,7 @@ using System.IO; using System.Collections; using System.Runtime.InteropServices; -namespace MediaBrowser.Common.Net +namespace MediaBrowser.Controller.IO { /// <summary> /// Type of share diff --git a/MediaBrowser.Controller/Library/LibraryManager.cs b/MediaBrowser.Controller/Library/LibraryManager.cs index 95a11e8fe..4087f9ef8 100644 --- a/MediaBrowser.Controller/Library/LibraryManager.cs +++ b/MediaBrowser.Controller/Library/LibraryManager.cs @@ -369,7 +369,7 @@ namespace MediaBrowser.Controller.Library /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - internal async Task ValidatePeople(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + internal async Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress) { // Clear the IBN cache ImagesByNameItemCache.Clear(); @@ -422,14 +422,14 @@ namespace MediaBrowser.Controller.Library double percent = numComplete; percent /= people.Count; - progress.Report(new TaskProgress { PercentComplete = 100 * percent }); + progress.Report(100 * percent); } })); } await Task.WhenAll(tasks).ConfigureAwait(false); - progress.Report(new TaskProgress { PercentComplete = 100 }); + progress.Report(100); _logger.Info("People validation complete"); } @@ -440,17 +440,17 @@ namespace MediaBrowser.Controller.Library /// <param name="progress">The progress.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - internal async Task ValidateMediaLibrary(IProgress<TaskProgress> progress, CancellationToken cancellationToken) + internal async Task ValidateMediaLibrary(IProgress<double> progress, CancellationToken cancellationToken) { _logger.Info("Validating media library"); await Kernel.RootFolder.RefreshMetadata(cancellationToken).ConfigureAwait(false); // Start by just validating the children of the root, but go no further - await Kernel.RootFolder.ValidateChildren(new Progress<TaskProgress> { }, cancellationToken, recursive: false); + await Kernel.RootFolder.ValidateChildren(new Progress<double> { }, cancellationToken, recursive: false); // Validate only the collection folders for each user, just to make them available as quickly as possible - var userCollectionFolderTasks = Kernel.Users.AsParallel().Select(user => user.ValidateCollectionFolders(new Progress<TaskProgress> { }, cancellationToken)); + var userCollectionFolderTasks = Kernel.Users.AsParallel().Select(user => user.ValidateCollectionFolders(new Progress<double> { }, cancellationToken)); await Task.WhenAll(userCollectionFolderTasks).ConfigureAwait(false); // Now validate the entire media library @@ -458,7 +458,7 @@ namespace MediaBrowser.Controller.Library foreach (var user in Kernel.Users) { - await user.ValidateMediaLibrary(new Progress<TaskProgress> { }, cancellationToken).ConfigureAwait(false); + await user.ValidateMediaLibrary(new Progress<double> { }, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index c2b11ae32..0bf3e6c1f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -67,7 +67,6 @@ <Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.Core" /> <Reference Include="System.Data" /> - <Reference Include="System.Deployment" /> <Reference Include="System.Drawing" /> <Reference Include="System.Net" /> <Reference Include="System.Runtime.Serialization" /> @@ -106,6 +105,7 @@ <Compile Include="Entities\Year.cs" /> <Compile Include="Extensions\XmlExtensions.cs" /> <Compile Include="IO\FileSystemManager.cs" /> + <Compile Include="IO\NetworkShares.cs" /> <Compile Include="Library\ChildrenChangedEventArgs.cs" /> <Compile Include="Library\DtoBuilder.cs" /> <Compile Include="Library\Profiler.cs" /> diff --git a/MediaBrowser.Controller/ScheduledTasks/ChapterImagesTask.cs b/MediaBrowser.Controller/ScheduledTasks/ChapterImagesTask.cs index 21f1bce5a..d3d30ed77 100644 --- a/MediaBrowser.Controller/ScheduledTasks/ChapterImagesTask.cs +++ b/MediaBrowser.Controller/ScheduledTasks/ChapterImagesTask.cs @@ -31,7 +31,7 @@ namespace MediaBrowser.Controller.ScheduledTasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) { var videos = Kernel.RootFolder.RecursiveChildren.OfType<Video>().Where(v => v.Chapters != null).ToList(); @@ -59,7 +59,7 @@ namespace MediaBrowser.Controller.ScheduledTasks double percent = numComplete; percent /= videos.Count; - progress.Report(new TaskProgress { PercentComplete = 100 * percent }); + progress.Report(100 * percent); } } })); diff --git a/MediaBrowser.Controller/ScheduledTasks/ImageCleanupTask.cs b/MediaBrowser.Controller/ScheduledTasks/ImageCleanupTask.cs index c16f714db..57fc280de 100644 --- a/MediaBrowser.Controller/ScheduledTasks/ImageCleanupTask.cs +++ b/MediaBrowser.Controller/ScheduledTasks/ImageCleanupTask.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Controller.ScheduledTasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected override async Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + protected override async Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) { await EnsureChapterImages(cancellationToken).ConfigureAwait(false); @@ -83,7 +83,7 @@ namespace MediaBrowser.Controller.ScheduledTasks double percent = numComplete; percent /= files.Count; - progress.Report(new TaskProgress { PercentComplete = 100 * percent }); + progress.Report(100 * percent); } })); diff --git a/MediaBrowser.Controller/ScheduledTasks/PeopleValidationTask.cs b/MediaBrowser.Controller/ScheduledTasks/PeopleValidationTask.cs index a5f87f212..0fdb91898 100644 --- a/MediaBrowser.Controller/ScheduledTasks/PeopleValidationTask.cs +++ b/MediaBrowser.Controller/ScheduledTasks/PeopleValidationTask.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Controller.ScheduledTasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) { return Kernel.LibraryManager.ValidatePeople(cancellationToken, progress); } diff --git a/MediaBrowser.Controller/ScheduledTasks/PluginUpdateTask.cs b/MediaBrowser.Controller/ScheduledTasks/PluginUpdateTask.cs index 3a700d94d..3d79193d5 100644 --- a/MediaBrowser.Controller/ScheduledTasks/PluginUpdateTask.cs +++ b/MediaBrowser.Controller/ScheduledTasks/PluginUpdateTask.cs @@ -38,13 +38,13 @@ namespace MediaBrowser.Controller.ScheduledTasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected override async Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + protected override async Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) { - progress.Report(new TaskProgress { Description = "Checking for plugin updates", PercentComplete = 0 }); + progress.Report(0); var packagesToInstall = (await Kernel.InstallationManager.GetAvailablePluginUpdates(true, cancellationToken).ConfigureAwait(false)).ToList(); - progress.Report(new TaskProgress { PercentComplete = 10 }); + progress.Report(10); var numComplete = 0; @@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.ScheduledTasks double percent = numComplete; percent /= packagesToInstall.Count; - progress.Report(new TaskProgress { PercentComplete = (90 * percent) + 10 }); + progress.Report((90 * percent) + 10); } })); @@ -89,7 +89,7 @@ namespace MediaBrowser.Controller.ScheduledTasks await Task.WhenAll(tasks).ConfigureAwait(false); - progress.Report(new TaskProgress { PercentComplete = 100 }); + progress.Report(100); } /// <summary> diff --git a/MediaBrowser.Controller/ScheduledTasks/RefreshMediaLibraryTask.cs b/MediaBrowser.Controller/ScheduledTasks/RefreshMediaLibraryTask.cs index b01019fce..f0fcb8aba 100644 --- a/MediaBrowser.Controller/ScheduledTasks/RefreshMediaLibraryTask.cs +++ b/MediaBrowser.Controller/ScheduledTasks/RefreshMediaLibraryTask.cs @@ -36,11 +36,11 @@ namespace MediaBrowser.Controller.ScheduledTasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + protected override Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) { cancellationToken.ThrowIfCancellationRequested(); - progress.Report(new TaskProgress { PercentComplete = 0 }); + progress.Report(0); return Kernel.LibraryManager.ValidateMediaLibrary(progress, cancellationToken); } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index fe411baea..14ab663d3 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -70,6 +70,7 @@ <Compile Include="Logging\LogSeverity.cs" /> <Compile Include="MediaInfo\IBlurayExaminer.cs" /> <Compile Include="Net\HttpException.cs" /> + <Compile Include="Updates\CheckForUpdateResult.cs" /> <Compile Include="Updates\InstallationInfo.cs" /> <Compile Include="Updates\PackageType.cs" /> <Compile Include="Updates\PackageVersionClass.cs" /> @@ -97,7 +98,6 @@ <Compile Include="Tasks\TaskCompletionStatus.cs" /> <Compile Include="Tasks\TaskResult.cs" /> <Compile Include="Tasks\TaskInfo.cs" /> - <Compile Include="Tasks\TaskProgress.cs" /> <Compile Include="Tasks\TaskState.cs" /> <Compile Include="Tasks\TaskTriggerInfo.cs" /> <Compile Include="Updates\PackageInfo.cs" /> diff --git a/MediaBrowser.Model/Tasks/TaskInfo.cs b/MediaBrowser.Model/Tasks/TaskInfo.cs index 340bfac4a..50dcb3080 100644 --- a/MediaBrowser.Model/Tasks/TaskInfo.cs +++ b/MediaBrowser.Model/Tasks/TaskInfo.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.Model.Tasks /// </summary> /// <value>The progress.</value> [ProtoMember(3)] - public TaskProgress CurrentProgress { get; set; } + public double? CurrentProgressPercentage { get; set; } /// <summary> /// Gets or sets the id. diff --git a/MediaBrowser.Model/Tasks/TaskProgress.cs b/MediaBrowser.Model/Tasks/TaskProgress.cs deleted file mode 100644 index aadfc896e..000000000 --- a/MediaBrowser.Model/Tasks/TaskProgress.cs +++ /dev/null @@ -1,22 +0,0 @@ -using ProtoBuf; - -namespace MediaBrowser.Model.Tasks -{ - [ProtoContract] - public class TaskProgress - { - /// <summary> - /// Gets or sets the description. - /// </summary> - /// <value>The description.</value> - [ProtoMember(1)] - public string Description { get; set; } - - /// <summary> - /// Gets or sets the percent complete. - /// </summary> - /// <value>The percent complete.</value> - [ProtoMember(2)] - public double PercentComplete { get; set; } - } -} diff --git a/MediaBrowser.Model/Updates/CheckForUpdateResult.cs b/MediaBrowser.Model/Updates/CheckForUpdateResult.cs new file mode 100644 index 000000000..48c0b398c --- /dev/null +++ b/MediaBrowser.Model/Updates/CheckForUpdateResult.cs @@ -0,0 +1,22 @@ +using System; + +namespace MediaBrowser.Model.Updates +{ + /// <summary> + /// Class CheckForUpdateResult + /// </summary> + public class CheckForUpdateResult + { + /// <summary> + /// Gets or sets a value indicating whether this instance is update available. + /// </summary> + /// <value><c>true</c> if this instance is update available; otherwise, <c>false</c>.</value> + public bool IsUpdateAvailable { get; set; } + + /// <summary> + /// Gets or sets the available version. + /// </summary> + /// <value>The available version.</value> + public Version AvailableVersion { get; set; } + } +} diff --git a/MediaBrowser.Plugins.Trailers/ScheduledTasks/CurrentTrailerDownloadTask.cs b/MediaBrowser.Plugins.Trailers/ScheduledTasks/CurrentTrailerDownloadTask.cs index 90bd80caf..47206fca0 100644 --- a/MediaBrowser.Plugins.Trailers/ScheduledTasks/CurrentTrailerDownloadTask.cs +++ b/MediaBrowser.Plugins.Trailers/ScheduledTasks/CurrentTrailerDownloadTask.cs @@ -39,12 +39,12 @@ namespace MediaBrowser.Plugins.Trailers.ScheduledTasks /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - protected override async Task ExecuteInternal(CancellationToken cancellationToken, IProgress<TaskProgress> progress) + protected override async Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress) { // Get the list of trailers var trailers = await AppleTrailerListingDownloader.GetTrailerList(cancellationToken).ConfigureAwait(false); - progress.Report(new TaskProgress { PercentComplete = 1 }); + progress.Report(1); var trailersToDownload = trailers.Where(t => !IsOldTrailer(t.Video)).ToList(); @@ -74,7 +74,7 @@ namespace MediaBrowser.Plugins.Trailers.ScheduledTasks percent /= trailersToDownload.Count; // Leave 1% for DeleteOldTrailers - progress.Report(new TaskProgress { PercentComplete = (99 * percent) + 1 }); + progress.Report((99 * percent) + 1); } })); @@ -90,7 +90,7 @@ namespace MediaBrowser.Plugins.Trailers.ScheduledTasks DeleteOldTrailers(); } - progress.Report(new TaskProgress { PercentComplete = 100 }); + progress.Report(100); } /// <summary> diff --git a/MediaBrowser.Server.Uninstall/MediaBrowser.Server.Uninstall.csproj b/MediaBrowser.Server.Uninstall/MediaBrowser.Server.Uninstall.csproj index 3c51ce6a2..334a7d345 100644 --- a/MediaBrowser.Server.Uninstall/MediaBrowser.Server.Uninstall.csproj +++ b/MediaBrowser.Server.Uninstall/MediaBrowser.Server.Uninstall.csproj @@ -52,9 +52,9 @@ <None Include="App.config" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> - <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> - <Name>MediaBrowser.Common</Name> + <ProjectReference Include="..\MediaBrowser.ClickOnce\MediaBrowser.ClickOnce.csproj"> + <Project>{cc96bf3e-0bda-4809-bc4b-bb6d418f4a84}</Project> + <Name>MediaBrowser.ClickOnce</Name> </ProjectReference> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> diff --git a/MediaBrowser.Server.Uninstall/Program.cs b/MediaBrowser.Server.Uninstall/Program.cs index 13f4e90f5..4374e970c 100644 --- a/MediaBrowser.Server.Uninstall/Program.cs +++ b/MediaBrowser.Server.Uninstall/Program.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Updates; +using MediaBrowser.ClickOnce; using System; using System.IO; diff --git a/MediaBrowser.ServerApplication/App.xaml.cs b/MediaBrowser.ServerApplication/App.xaml.cs index cc6367127..919898aa3 100644 --- a/MediaBrowser.ServerApplication/App.xaml.cs +++ b/MediaBrowser.ServerApplication/App.xaml.cs @@ -1,14 +1,14 @@ -using MediaBrowser.Common.Kernel; -using MediaBrowser.Common.Updates; +using MediaBrowser.ClickOnce; +using MediaBrowser.Common.Kernel; using MediaBrowser.Controller; using MediaBrowser.IsoMounter; using MediaBrowser.Logging.Nlog; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Updates; using MediaBrowser.Server.Uninstall; using MediaBrowser.ServerApplication.Implementations; using Microsoft.Win32; using System; -using System.Deployment.Application; using System.Diagnostics; using System.IO; using System.Linq; @@ -71,7 +71,7 @@ namespace MediaBrowser.ServerApplication /// Gets or sets the log file path. /// </summary> /// <value>The log file path.</value> - private string LogFilePath { get; set; } + public string LogFilePath { get; private set; } /// <summary> /// Initializes a new instance of the <see cref="App" /> class. @@ -235,24 +235,9 @@ namespace MediaBrowser.ServerApplication /// </summary> private void ConfigureClickOnceStartup() { - if (!ApplicationDeployment.IsNetworkDeployed) - { - return; - } - try { - var clickOnceHelper = new ClickOnceHelper(PublisherName, ProductName, SuiteName); - - if (Kernel.Configuration.RunAtStartup) - { - clickOnceHelper.UpdateUninstallParameters(UninstallerFileName); - clickOnceHelper.AddShortcutToStartup(); - } - else - { - clickOnceHelper.RemoveShortcutFromStartup(); - } + ClickOnceHelper.ConfigureClickOnceStartupIfInstalled(PublisherName, ProductName, SuiteName, Kernel.Configuration.RunAtStartup, UninstallerFileName); LastRunAtStartupValue = Kernel.Configuration.RunAtStartup; } @@ -469,5 +454,36 @@ namespace MediaBrowser.ServerApplication RenderOptions.SetBitmapScalingMode(bitmap, BitmapScalingMode.Fant); return bitmap; } + + /// <summary> + /// Gets or sets a value indicating whether this instance can self update. + /// </summary> + /// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value> + public bool CanSelfUpdate + { + get { return ClickOnceHelper.IsNetworkDeployed; } + } + + /// <summary> + /// Checks for update. + /// </summary> + /// <param name="cancellationToken">The cancellation token.</param> + /// <param name="progress">The progress.</param> + /// <returns>Task{CheckForUpdateResult}.</returns> + public Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress) + { + return new ApplicationUpdateCheck().CheckForApplicationUpdate(cancellationToken, progress); + } + + /// <summary> + /// Updates the application. + /// </summary> + /// <param name="cancellationToken">The cancellation token.</param> + /// <param name="progress">The progress.</param> + /// <returns>Task.</returns> + public Task UpdateApplication(CancellationToken cancellationToken, IProgress<double> progress) + { + return new ApplicationUpdater().UpdateApplication(cancellationToken, progress); + } } } diff --git a/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs b/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs index 9645b93dc..02dd6fb9c 100644 --- a/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs +++ b/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs @@ -41,7 +41,7 @@ namespace MediaBrowser.ServerApplication _logger = logger; InitializeComponent(); - lblVersion.Content = "Version: " + Kernel.Instance.DisplayVersion; + lblVersion.Content = "Version: " + Kernel.Instance.ApplicationVersion; foreach (var user in Kernel.Instance.Users) ddlProfile.Items.Add(user); ddlProfile.Items.Insert(0,new User {Name = "Physical"}); diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index ff8be69e4..2f9169123 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -138,7 +138,6 @@ <Reference Include="System.Data.SQLite.Linq"> <HintPath>..\packages\System.Data.SQLite.1.0.84.0\lib\net45\System.Data.SQLite.Linq.dll</HintPath> </Reference> - <Reference Include="System.Deployment" /> <Reference Include="System.Drawing" /> <Reference Include="System.Runtime.Remoting" /> <Reference Include="System.Web.Extensions" /> @@ -240,6 +239,10 @@ <Project>{07b509c0-0c28-4f3f-8963-5263281f7e3d}</Project> <Name>BDInfo</Name> </ProjectReference> + <ProjectReference Include="..\MediaBrowser.ClickOnce\MediaBrowser.ClickOnce.csproj"> + <Project>{cc96bf3e-0bda-4809-bc4b-bb6d418f4a84}</Project> + <Name>MediaBrowser.ClickOnce</Name> + </ProjectReference> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> <Name>MediaBrowser.Common</Name> diff --git a/MediaBrowser.UI.Uninstall/MediaBrowser.UI.Uninstall.csproj b/MediaBrowser.UI.Uninstall/MediaBrowser.UI.Uninstall.csproj index 060d86d8e..b54eabc48 100644 --- a/MediaBrowser.UI.Uninstall/MediaBrowser.UI.Uninstall.csproj +++ b/MediaBrowser.UI.Uninstall/MediaBrowser.UI.Uninstall.csproj @@ -52,9 +52,9 @@ <None Include="App.config" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> - <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> - <Name>MediaBrowser.Common</Name> + <ProjectReference Include="..\MediaBrowser.ClickOnce\MediaBrowser.ClickOnce.csproj"> + <Project>{cc96bf3e-0bda-4809-bc4b-bb6d418f4a84}</Project> + <Name>MediaBrowser.ClickOnce</Name> </ProjectReference> </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> diff --git a/MediaBrowser.UI.Uninstall/Program.cs b/MediaBrowser.UI.Uninstall/Program.cs index 9110a3eaf..14c3d3abf 100644 --- a/MediaBrowser.UI.Uninstall/Program.cs +++ b/MediaBrowser.UI.Uninstall/Program.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Updates; +using MediaBrowser.ClickOnce; using System; using System.IO; diff --git a/MediaBrowser.UI.sln b/MediaBrowser.UI.sln index 8f4f3145a..dc58dc089 100644 --- a/MediaBrowser.UI.sln +++ b/MediaBrowser.UI.sln @@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.UI.Controls", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Logging.NLog", "MediaBrowser.Logging.NLog\MediaBrowser.Logging.NLog.csproj", "{67310740-0EC4-4DC2-9921-33DF38B20167}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ClickOnce", "MediaBrowser.ClickOnce\MediaBrowser.ClickOnce.csproj", "{CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -155,6 +157,16 @@ Global {67310740-0EC4-4DC2-9921-33DF38B20167}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {67310740-0EC4-4DC2-9921-33DF38B20167}.Release|Mixed Platforms.Build.0 = Release|Any CPU {67310740-0EC4-4DC2-9921-33DF38B20167}.Release|x86.ActiveCfg = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|x86.ActiveCfg = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|Any CPU.Build.0 = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MediaBrowser.UI/App.xaml.cs b/MediaBrowser.UI/App.xaml.cs index 5867f1119..b98ce8e6c 100644 --- a/MediaBrowser.UI/App.xaml.cs +++ b/MediaBrowser.UI/App.xaml.cs @@ -1,33 +1,33 @@ -using System.Deployment.Application; -using System.Net.Cache; -using System.Windows.Media; -using MediaBrowser.ApiInteraction; +using MediaBrowser.ApiInteraction; +using MediaBrowser.ClickOnce; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Common.Kernel; -using MediaBrowser.Common.Updates; using MediaBrowser.IsoMounter; using MediaBrowser.Logging.Nlog; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; +using MediaBrowser.Model.Updates; using MediaBrowser.Model.Weather; using MediaBrowser.UI.Controller; using MediaBrowser.UI.Controls; using MediaBrowser.UI.Pages; using MediaBrowser.UI.Uninstall; +using Microsoft.Win32; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Linq; +using System.Net.Cache; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using System.Windows.Media; using System.Windows.Media.Imaging; -using Microsoft.Win32; namespace MediaBrowser.UI { @@ -74,7 +74,7 @@ namespace MediaBrowser.UI /// Gets or sets the log file path. /// </summary> /// <value>The log file path.</value> - private string LogFilePath { get; set; } + public string LogFilePath { get; private set; } /// <summary> /// Occurs when [property changed]. @@ -916,24 +916,9 @@ namespace MediaBrowser.UI /// </summary> private void ConfigureClickOnceStartup() { - if (!ApplicationDeployment.IsNetworkDeployed) - { - return; - } - try { - var clickOnceHelper = new ClickOnceHelper(PublisherName, ProductName, SuiteName); - - if (Kernel.Configuration.RunAtStartup) - { - clickOnceHelper.UpdateUninstallParameters(UninstallerFileName); - clickOnceHelper.AddShortcutToStartup(); - } - else - { - clickOnceHelper.RemoveShortcutFromStartup(); - } + ClickOnceHelper.ConfigureClickOnceStartupIfInstalled(PublisherName, ProductName, SuiteName, Kernel.Configuration.RunAtStartup, UninstallerFileName); LastRunAtStartupValue = Kernel.Configuration.RunAtStartup; } @@ -1004,5 +989,36 @@ namespace MediaBrowser.UI RenderOptions.SetBitmapScalingMode(bitmap, BitmapScalingMode.Fant); return bitmap; } + + /// <summary> + /// Gets or sets a value indicating whether this instance can self update. + /// </summary> + /// <value><c>true</c> if this instance can self update; otherwise, <c>false</c>.</value> + public bool CanSelfUpdate + { + get { return ClickOnceHelper.IsNetworkDeployed; } + } + + /// <summary> + /// Checks for update. + /// </summary> + /// <param name="cancellationToken">The cancellation token.</param> + /// <param name="progress">The progress.</param> + /// <returns>Task{CheckForUpdateResult}.</returns> + public Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress) + { + return new ApplicationUpdateCheck().CheckForApplicationUpdate(cancellationToken, progress); + } + + /// <summary> + /// Updates the application. + /// </summary> + /// <param name="cancellationToken">The cancellation token.</param> + /// <param name="progress">The progress.</param> + /// <returns>Task.</returns> + public Task UpdateApplication(CancellationToken cancellationToken, IProgress<double> progress) + { + return new ApplicationUpdater().UpdateApplication(cancellationToken, progress); + } } } diff --git a/MediaBrowser.UI/Extensions/Extensions.cs b/MediaBrowser.UI/Extensions/Extensions.cs new file mode 100644 index 000000000..1d0d7d1c2 --- /dev/null +++ b/MediaBrowser.UI/Extensions/Extensions.cs @@ -0,0 +1,26 @@ +using System; +using System.Windows.Threading; + +namespace MediaBrowser.UI.Extensions +{ + public static class Extensions + { + /// <summary> + /// Invokes an action after a specified delay + /// </summary> + /// <param name="dispatcher">The dispatcher.</param> + /// <param name="action">The action.</param> + /// <param name="delayMs">The delay ms.</param> + public static void InvokeWithDelay(this Dispatcher dispatcher, Action action, long delayMs) + { + var timer = new DispatcherTimer(DispatcherPriority.Normal, dispatcher); + timer.Interval = TimeSpan.FromMilliseconds(delayMs); + timer.Tick += (sender, args) => + { + timer.Stop(); + action(); + }; + timer.Start(); + } + } +} diff --git a/MediaBrowser.UI/MainWindow.xaml.cs b/MediaBrowser.UI/MainWindow.xaml.cs index bc12b92e5..d3307e913 100644 --- a/MediaBrowser.UI/MainWindow.xaml.cs +++ b/MediaBrowser.UI/MainWindow.xaml.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; +using MediaBrowser.UI.Extensions; namespace MediaBrowser.UI { diff --git a/MediaBrowser.UI/MediaBrowser.UI.csproj b/MediaBrowser.UI/MediaBrowser.UI.csproj index a8d7c9b4c..f25707afa 100644 --- a/MediaBrowser.UI/MediaBrowser.UI.csproj +++ b/MediaBrowser.UI/MediaBrowser.UI.csproj @@ -116,7 +116,6 @@ <Reference Include="System" /> <Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.Data" /> - <Reference Include="System.Deployment" /> <Reference Include="System.Drawing" /> <Reference Include="System.Net" /> <Reference Include="System.Net.Http" /> @@ -153,6 +152,7 @@ <Compile Include="Controls\NotificationMessage.xaml.cs"> <DependentUpon>NotificationMessage.xaml</DependentUpon> </Compile> + <Compile Include="Extensions\Extensions.cs" /> <Compile Include="HiddenWindow.xaml.cs"> <DependentUpon>HiddenWindow.xaml</DependentUpon> </Compile> @@ -300,6 +300,10 @@ <Project>{921c0f64-fda7-4e9f-9e73-0cb0eedb2422}</Project> <Name>MediaBrowser.ApiInteraction</Name> </ProjectReference> + <ProjectReference Include="..\MediaBrowser.ClickOnce\MediaBrowser.ClickOnce.csproj"> + <Project>{cc96bf3e-0bda-4809-bc4b-bb6d418f4a84}</Project> + <Name>MediaBrowser.ClickOnce</Name> + </ProjectReference> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> <Name>MediaBrowser.Common</Name> diff --git a/MediaBrowser.WebDashboard/Html/scripts/DashboardPage.js b/MediaBrowser.WebDashboard/Html/scripts/DashboardPage.js index 93163de79..848c6b1a0 100644 --- a/MediaBrowser.WebDashboard/Html/scripts/DashboardPage.js +++ b/MediaBrowser.WebDashboard/Html/scripts/DashboardPage.js @@ -252,8 +252,8 @@ html += task.Name; if (task.State == "Running") { - var progress = task.CurrentProgress || { PercentComplete: 0 }; - html += '<span style="color:#267F00;margin-right:5px;font-weight:bold;"> - ' + Math.round(progress.PercentComplete) + '%</span>'; + var progress = Math.round(task.CurrentProgressPercentage || 0); + html += '<span style="color:#267F00;margin-right:5px;font-weight:bold;"> - ' + progress + '%</span>'; html += '<button type="button" data-icon="stop" data-iconpos="notext" data-inline="true" data-theme="b" data-mini="true" onclick="DashboardPage.stopTask(\'' + task.Id + '\');">Stop</button>'; } diff --git a/MediaBrowser.WebDashboard/Html/scripts/ScheduledTasksPage.js b/MediaBrowser.WebDashboard/Html/scripts/ScheduledTasksPage.js index d822db722..fe42396b4 100644 --- a/MediaBrowser.WebDashboard/Html/scripts/ScheduledTasksPage.js +++ b/MediaBrowser.WebDashboard/Html/scripts/ScheduledTasksPage.js @@ -119,8 +119,7 @@ } else if (task.State == "Running") { - var progress = task.CurrentProgress || { PercentComplete: 0 }; - progress = Math.round(progress.PercentComplete); + var progress = Math.round(task.CurrentProgressPercentage || 0); html += '<p><progress max="100" value="' + progress + '" title="' + progress + '%">'; html += '' + progress + '%'; diff --git a/MediaBrowser.sln b/MediaBrowser.sln index a9fae4edb..27b0f81b5 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -51,6 +51,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.WorldWe EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Logging.NLog", "MediaBrowser.Logging.NLog\MediaBrowser.Logging.NLog.csproj", "{67310740-0EC4-4DC2-9921-33DF38B20167}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ClickOnce", "MediaBrowser.ClickOnce\MediaBrowser.ClickOnce.csproj", "{CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -335,6 +337,20 @@ Global {67310740-0EC4-4DC2-9921-33DF38B20167}.Release|Win32.ActiveCfg = Release|Any CPU {67310740-0EC4-4DC2-9921-33DF38B20167}.Release|x64.ActiveCfg = Release|Any CPU {67310740-0EC4-4DC2-9921-33DF38B20167}.Release|x86.ActiveCfg = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|Win32.ActiveCfg = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|x64.ActiveCfg = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Debug|x86.ActiveCfg = Debug|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|Any CPU.Build.0 = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|Win32.ActiveCfg = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|x64.ActiveCfg = Release|Any CPU + {CC96BF3E-0BDA-4809-BC4B-BB6D418F4A84}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE |
