This commit is contained in:
Eric Reed 2013-09-23 12:28:44 -04:00
commit c6e57c6448
46 changed files with 479 additions and 376 deletions

View File

@ -110,16 +110,19 @@ namespace MediaBrowser.Api
{
var summary = new GameSystemSummary
{
Name = system.Name
Name = system.GameSystemName,
DisplayName = system.Name
};
var items = user == null ? system.RecursiveChildren : system.GetRecursiveChildren(user);
var games = items.OfType<Game>().ToList();
summary.ClientInstalledGameCount = games.Count(i => !i.IsInstalledOnClient);
summary.GameCount = games.Count;
summary.GameFileExtensions = games.Select(i => Path.GetExtension(i.Path))
summary.GameFileExtensions = games.Where(i => !i.IsInstalledOnClient).Select(i => Path.GetExtension(i.Path))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();

View File

@ -40,17 +40,17 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Common, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.Common, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Common.dll</HintPath>
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Interfaces, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.Interfaces, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Interfaces.dll</HintPath>
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Text.3.9.59\lib\net35\ServiceStack.Text.dll</HintPath>
<HintPath>..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@ -132,7 +132,7 @@ namespace MediaBrowser.Api
if (request.PackageType == PackageType.UserInstalled || request.PackageType == PackageType.All)
{
result.AddRange(_installationManager.GetAvailablePluginUpdates(false, CancellationToken.None).Result.ToList());
result.AddRange(_installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, false, CancellationToken.None).Result.ToList());
}
else if (request.PackageType == PackageType.System || request.PackageType == PackageType.All)
@ -194,7 +194,7 @@ namespace MediaBrowser.Api
public void Post(InstallPackage request)
{
var package = string.IsNullOrEmpty(request.Version) ?
_installationManager.GetLatestCompatibleVersion(request.Name, request.UpdateClass).Result :
_installationManager.GetLatestCompatibleVersion(request.Name, _appHost.ApplicationVersion, request.UpdateClass).Result :
_installationManager.GetPackage(request.Name, request.UpdateClass, Version.Parse(request.Version)).Result;
if (package == null)

View File

@ -45,7 +45,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, ItemCounts, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
/// <summary>

View File

@ -43,7 +43,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, ItemCounts, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
/// <summary>

View File

@ -48,7 +48,7 @@ namespace MediaBrowser.Api.UserLibrary
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, ItemCounts, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, OverviewHtml, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
/// <summary>

View File

@ -12,7 +12,6 @@ using ServiceStack.ServiceHost;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Api.UserLibrary
{
@ -64,6 +63,9 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "Genres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Genres { get; set; }
[ApiMember(Name = "AllGenres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string AllGenres { get; set; }
/// <summary>
/// Limit results to items containing specific studios
/// </summary>
@ -609,43 +611,42 @@ namespace MediaBrowser.Api.UserLibrary
items = items.Where(item => imageTypes.Any(imageType => HasImage(item, imageType)));
}
var genres = request.Genres;
// Apply genre filter
if (!string.IsNullOrEmpty(request.Genres))
{
var vals = request.Genres.Split(',');
items = items.Where(f => vals.Any(v => f.Genres.Contains(v, StringComparer.OrdinalIgnoreCase)));
}
// Apply genre filter
if (!string.IsNullOrEmpty(genres))
if (!string.IsNullOrEmpty(request.AllGenres))
{
var vals = genres.Split(',');
items = items.Where(f => f.Genres != null && vals.Any(v => f.Genres.Contains(v, StringComparer.OrdinalIgnoreCase)));
var vals = request.AllGenres.Split(',');
items = items.Where(f => vals.All(v => f.Genres.Contains(v, StringComparer.OrdinalIgnoreCase)));
}
var studios = request.Studios;
// Apply studio filter
if (!string.IsNullOrEmpty(studios))
if (!string.IsNullOrEmpty(request.Studios))
{
var vals = studios.Split(',');
items = items.Where(f => f.Studios != null && vals.Any(v => f.Studios.Contains(v, StringComparer.OrdinalIgnoreCase)));
var vals = request.Studios.Split(',');
items = items.Where(f => vals.Any(v => f.Studios.Contains(v, StringComparer.OrdinalIgnoreCase)));
}
var years = request.Years;
// Apply year filter
if (!string.IsNullOrEmpty(years))
if (!string.IsNullOrEmpty(request.Years))
{
var vals = years.Split(',').Select(int.Parse);
var vals = request.Years.Split(',').Select(int.Parse).ToList();
items = items.Where(f => f.ProductionYear.HasValue && vals.Contains(f.ProductionYear.Value));
}
var personName = request.Person;
// Apply person filter
if (!string.IsNullOrEmpty(personName))
if (!string.IsNullOrEmpty(request.Person))
{
var personTypes = request.PersonTypes;
if (string.IsNullOrEmpty(personTypes))
{
items = items.Where(item => item.People != null && item.People.Any(p => string.Equals(p.Name, personName, StringComparison.OrdinalIgnoreCase)));
items = items.Where(item => item.People != null && item.People.Any(p => string.Equals(p.Name, request.Person, StringComparison.OrdinalIgnoreCase)));
}
else
{
@ -654,7 +655,7 @@ namespace MediaBrowser.Api.UserLibrary
items = items.Where(item =>
item.People != null &&
item.People.Any(p =>
p.Name.Equals(personName, StringComparison.OrdinalIgnoreCase) && (types.Contains(p.Type, StringComparer.OrdinalIgnoreCase) || types.Contains(p.Role, StringComparer.OrdinalIgnoreCase))));
p.Name.Equals(request.Person, StringComparison.OrdinalIgnoreCase) && (types.Contains(p.Type, StringComparer.OrdinalIgnoreCase) || types.Contains(p.Role, StringComparer.OrdinalIgnoreCase))));
}
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" />
</packages>

View File

@ -41,7 +41,7 @@
</Reference>
<Reference Include="ServiceStack.Text, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Text.3.9.59\lib\net35\ServiceStack.Text.dll</HintPath>
<HintPath>..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="SimpleInjector, Version=2.3.5.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>

View File

@ -225,9 +225,9 @@ namespace MediaBrowser.Common.Implementations.Updates
/// Determines whether [is package version up to date] [the specified package version info].
/// </summary>
/// <param name="packageVersionInfo">The package version info.</param>
/// <param name="applicationVersion">The application version.</param>
/// <param name="currentServerVersion">The current server version.</param>
/// <returns><c>true</c> if [is package version up to date] [the specified package version info]; otherwise, <c>false</c>.</returns>
private bool IsPackageVersionUpToDate(PackageVersionInfo packageVersionInfo, Version applicationVersion)
private bool IsPackageVersionUpToDate(PackageVersionInfo packageVersionInfo, Version currentServerVersion)
{
if (string.IsNullOrEmpty(packageVersionInfo.requiredVersionStr))
{
@ -236,7 +236,7 @@ namespace MediaBrowser.Common.Implementations.Updates
Version requiredVersion;
return Version.TryParse(packageVersionInfo.requiredVersionStr, out requiredVersion) && applicationVersion >= requiredVersion;
return Version.TryParse(packageVersionInfo.requiredVersionStr, out requiredVersion) && currentServerVersion >= requiredVersion;
}
/// <summary>
@ -264,13 +264,14 @@ namespace MediaBrowser.Common.Implementations.Updates
/// Gets the latest compatible version.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="currentServerVersion">The current server version.</param>
/// <param name="classification">The classification.</param>
/// <returns>Task{PackageVersionInfo}.</returns>
public async Task<PackageVersionInfo> GetLatestCompatibleVersion(string name, PackageVersionClass classification = PackageVersionClass.Release)
public async Task<PackageVersionInfo> GetLatestCompatibleVersion(string name, Version currentServerVersion, PackageVersionClass classification = PackageVersionClass.Release)
{
var packages = await GetAvailablePackages(CancellationToken.None).ConfigureAwait(false);
return GetLatestCompatibleVersion(packages, name, classification);
return GetLatestCompatibleVersion(packages, name, currentServerVersion, classification);
}
/// <summary>
@ -278,9 +279,10 @@ namespace MediaBrowser.Common.Implementations.Updates
/// </summary>
/// <param name="availablePackages">The available packages.</param>
/// <param name="name">The name.</param>
/// <param name="currentServerVersion">The current server version.</param>
/// <param name="classification">The classification.</param>
/// <returns>PackageVersionInfo.</returns>
public PackageVersionInfo GetLatestCompatibleVersion(IEnumerable<PackageInfo> availablePackages, string name, PackageVersionClass classification = PackageVersionClass.Release)
public PackageVersionInfo GetLatestCompatibleVersion(IEnumerable<PackageInfo> availablePackages, string name, Version currentServerVersion, PackageVersionClass classification = PackageVersionClass.Release)
{
var package = availablePackages.FirstOrDefault(p => p.name.Equals(name, StringComparison.OrdinalIgnoreCase));
@ -291,23 +293,20 @@ namespace MediaBrowser.Common.Implementations.Updates
return package.versions
.OrderByDescending(v => v.version)
.FirstOrDefault(v => v.classification <= classification && IsPackageVersionUpToDate(v, _applicationHost.ApplicationVersion));
.FirstOrDefault(v => v.classification <= classification && IsPackageVersionUpToDate(v, currentServerVersion));
}
/// <summary>
/// Gets the available plugin updates.
/// </summary>
/// <param name="currentServerVersion">The current server version.</param>
/// <param name="withAutoUpdateEnabled">if set to <c>true</c> [with auto update enabled].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{PackageVersionInfo}}.</returns>
public async Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(bool withAutoUpdateEnabled, CancellationToken cancellationToken)
public async Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(Version currentServerVersion, bool withAutoUpdateEnabled, CancellationToken cancellationToken)
{
var catalog = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
return FilterCatalog(catalog, withAutoUpdateEnabled);
}
protected IEnumerable<PackageVersionInfo> FilterCatalog(IEnumerable<PackageInfo> catalog, bool withAutoUpdateEnabled)
{
var plugins = _applicationHost.Plugins.ToList();
if (withAutoUpdateEnabled)
@ -320,7 +319,7 @@ namespace MediaBrowser.Common.Implementations.Updates
// Figure out what needs to be installed
var packages = plugins.Select(p =>
{
var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Configuration.UpdateClass);
var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, currentServerVersion, p.Configuration.UpdateClass);
return latestPluginInfo != null && latestPluginInfo.version != null && latestPluginInfo.version > p.Version ? latestPluginInfo : null;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NLog" version="2.0.1.2" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" />
<package id="SimpleInjector" version="2.3.5" targetFramework="net45" />
</packages>

View File

@ -37,17 +37,17 @@
</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="ServiceStack.Common, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.Common, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Common.dll</HintPath>
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Interfaces, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.Interfaces, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Interfaces.dll</HintPath>
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Text.3.9.59\lib\net35\ServiceStack.Text.dll</HintPath>
<HintPath>..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@ -76,26 +76,29 @@ namespace MediaBrowser.Common.Updates
/// Gets the latest compatible version.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="currentServerVersion">The current server version.</param>
/// <param name="classification">The classification.</param>
/// <returns>Task{PackageVersionInfo}.</returns>
Task<PackageVersionInfo> GetLatestCompatibleVersion(string name, PackageVersionClass classification = PackageVersionClass.Release);
Task<PackageVersionInfo> GetLatestCompatibleVersion(string name, Version currentServerVersion, PackageVersionClass classification = PackageVersionClass.Release);
/// <summary>
/// Gets the latest compatible version.
/// </summary>
/// <param name="availablePackages">The available packages.</param>
/// <param name="name">The name.</param>
/// <param name="currentServerVersion">The current server version.</param>
/// <param name="classification">The classification.</param>
/// <returns>PackageVersionInfo.</returns>
PackageVersionInfo GetLatestCompatibleVersion(IEnumerable<PackageInfo> availablePackages, string name, PackageVersionClass classification = PackageVersionClass.Release);
PackageVersionInfo GetLatestCompatibleVersion(IEnumerable<PackageInfo> availablePackages, string name, Version currentServerVersion, PackageVersionClass classification = PackageVersionClass.Release);
/// <summary>
/// Gets the available plugin updates.
/// </summary>
/// <param name="currentServerVersion">The current server version.</param>
/// <param name="withAutoUpdateEnabled">if set to <c>true</c> [with auto update enabled].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{PackageVersionInfo}}.</returns>
Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(bool withAutoUpdateEnabled, CancellationToken cancellationToken);
Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(Version currentServerVersion, bool withAutoUpdateEnabled, CancellationToken cancellationToken);
/// <summary>
/// Installs the package.

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ServiceStack.Common" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" />
</packages>

View File

@ -1004,7 +1004,8 @@ namespace MediaBrowser.Controller.Entities
throw new ArgumentNullException();
}
var list = new List<BaseItem>(10000);
var initialCount = _children == null ? 100 : _children.Count;
var list = new List<BaseItem>(initialCount);
AddRecursiveChildrenInternal(user, includeLinkedChildren, list);

View File

@ -24,6 +24,12 @@ namespace MediaBrowser.Controller.Entities
/// <value>The players supported.</value>
public int? PlayersSupported { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is installed on client.
/// </summary>
/// <value><c>true</c> if this instance is installed on client; otherwise, <c>false</c>.</value>
public bool IsInstalledOnClient { get; set; }
/// <summary>
/// Gets or sets the game system.
/// </summary>

View File

@ -19,5 +19,11 @@ namespace MediaBrowser.Controller.Entities
return Id;
}
}
/// <summary>
/// Gets or sets the game system.
/// </summary>
/// <value>The game system.</value>
public string GameSystemName { get; set; }
}
}

View File

@ -139,6 +139,7 @@ namespace MediaBrowser.Controller.Providers
break;
}
case "CriticRating":
{
var text = reader.ReadElementContentAsString();
@ -150,6 +151,7 @@ namespace MediaBrowser.Controller.Providers
break;
}
case "Budget":
{
var text = reader.ReadElementContentAsString();
@ -161,6 +163,7 @@ namespace MediaBrowser.Controller.Providers
break;
}
case "Revenue":
{
var text = reader.ReadElementContentAsString();
@ -172,6 +175,7 @@ namespace MediaBrowser.Controller.Providers
break;
}
case "SortTitle":
{
var val = reader.ReadElementContentAsString();
@ -466,6 +470,7 @@ namespace MediaBrowser.Controller.Providers
break;
}
case "ReleaseYear":
case "ProductionYear":
{
var val = reader.ReadElementContentAsString();
@ -555,6 +560,37 @@ namespace MediaBrowser.Controller.Providers
}
break;
case "Players":
{
var val = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(val))
{
int num;
// All external meta is saving this as '.' for decimal I believe...but just to be sure
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out num))
{
var game = item as Game;
if (game != null)
{
game.PlayersSupported = num;
}
}
}
break;
}
case "GameSystem":
{
var val = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(val))
{
var game = item as Game;
if (game != null)
{
game.GameSystem = val;
}
}
break;
}
case "MusicbrainzId":
{
var mbz = reader.ReadElementContentAsString();

View File

@ -202,6 +202,18 @@ namespace MediaBrowser.Controller.Providers
return NeedsRefreshInternal(item, data);
}
/// <summary>
/// Gets a value indicating whether [enforce dont fetch metadata].
/// </summary>
/// <value><c>true</c> if [enforce dont fetch metadata]; otherwise, <c>false</c>.</value>
public virtual bool EnforceDontFetchMetadata
{
get
{
return true;
}
}
/// <summary>
/// Needses the refresh internal.
/// </summary>

View File

@ -13,6 +13,12 @@ namespace MediaBrowser.Model.Dto
/// <value>The name.</value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string DisplayName { get; set; }
/// <summary>
/// Gets or sets the game count.
/// </summary>
@ -25,6 +31,12 @@ namespace MediaBrowser.Model.Dto
/// <value>The game extensions.</value>
public List<string> GameFileExtensions { get; set; }
/// <summary>
/// Gets or sets the client installed game count.
/// </summary>
/// <value>The client installed game count.</value>
public int ClientInstalledGameCount { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="GameSystemSummary"/> class.
/// </summary>

View File

@ -37,6 +37,10 @@ namespace MediaBrowser.Model.Entities
/// <summary>
/// The runtime
/// </summary>
Runtime
Runtime,
/// <summary>
/// The official rating
/// </summary>
OfficialRating
}
}

View File

@ -51,11 +51,6 @@ namespace MediaBrowser.Model.Querying
/// </summary>
HomePageUrl,
/// <summary>
/// Child count, recursive child count, etc
/// </summary>
ItemCounts,
/// <summary>
/// The fields that the server supports indexing on
/// </summary>

View File

@ -92,6 +92,12 @@ namespace MediaBrowser.Model.Querying
/// <value>The genres.</value>
public string[] Genres { get; set; }
/// <summary>
/// Limit results to items containing specific genres
/// </summary>
/// <value>The genres.</value>
public string[] AllGenres { get; set; }
/// <summary>
/// Limit results to items containing specific studios
/// </summary>

View File

@ -384,7 +384,10 @@ namespace MediaBrowser.Providers.MediaInfo
if (!string.IsNullOrWhiteSpace(officialRating))
{
video.OfficialRating = officialRating;
if (!video.LockedFields.Contains(MetadataFields.OfficialRating))
{
video.OfficialRating = officialRating;
}
}
}

View File

@ -317,7 +317,7 @@ namespace MediaBrowser.Providers.Movies
var boxset = item as BoxSet;
if (boxset != null)
{
// See if any movies have a collection id already
// See if any movies have a collection id already
var collId = boxset.Children.Concat(boxset.GetLinkedChildren()).OfType<Video>()
.Select(i => i.GetProviderId(MetadataProviders.TmdbCollection))
.FirstOrDefault(i => i != null);
@ -462,7 +462,7 @@ namespace MediaBrowser.Providers.Movies
Logger.Info("MoviedbProvider: Ignoring " + item.Name + " because ID forced blank.");
return;
}
item.SetProviderId(MetadataProviders.Tmdb, id);
var mainResult = await FetchMainResult(item, id, cancellationToken).ConfigureAwait(false);
@ -586,14 +586,18 @@ namespace MediaBrowser.Providers.Movies
var ourRelease = movieData.releases.countries.FirstOrDefault(c => c.iso_3166_1.Equals(ConfigurationManager.Configuration.MetadataCountryCode, StringComparison.OrdinalIgnoreCase)) ?? new Country();
var usRelease = movieData.releases.countries.FirstOrDefault(c => c.iso_3166_1.Equals("US", StringComparison.OrdinalIgnoreCase)) ?? new Country();
var minimunRelease = movieData.releases.countries.OrderBy(c => c.release_date).FirstOrDefault() ?? new Country();
var ratingPrefix = ConfigurationManager.Configuration.MetadataCountryCode.Equals("us", StringComparison.OrdinalIgnoreCase) ? "" : ConfigurationManager.Configuration.MetadataCountryCode + "-";
movie.OfficialRating = !string.IsNullOrEmpty(ourRelease.certification)
? ratingPrefix + ourRelease.certification
: !string.IsNullOrEmpty(usRelease.certification)
? usRelease.certification
: !string.IsNullOrEmpty(minimunRelease.certification)
? minimunRelease.iso_3166_1 + "-" + minimunRelease.certification
: null;
if (!movie.LockedFields.Contains(MetadataFields.OfficialRating))
{
var ratingPrefix = ConfigurationManager.Configuration.MetadataCountryCode.Equals("us", StringComparison.OrdinalIgnoreCase) ? "" : ConfigurationManager.Configuration.MetadataCountryCode + "-";
movie.OfficialRating = !string.IsNullOrEmpty(ourRelease.certification)
? ratingPrefix + ourRelease.certification
: !string.IsNullOrEmpty(usRelease.certification)
? usRelease.certification
: !string.IsNullOrEmpty(minimunRelease.certification)
? minimunRelease.iso_3166_1 + "-" + minimunRelease.certification
: null;
}
if (ourRelease.release_date != default(DateTime))
{
@ -632,7 +636,7 @@ namespace MediaBrowser.Providers.Movies
}
//if that didn't find a rating and we are a boxset, use the one from our first child
if (movie.OfficialRating == null && movie is BoxSet)
if (movie.OfficialRating == null && movie is BoxSet && !movie.LockedFields.Contains(MetadataFields.OfficialRating))
{
var boxset = movie as BoxSet;
Logger.Info("MovieDbProvider - Using rating of first child of boxset...");

View File

@ -563,7 +563,7 @@ namespace MediaBrowser.Providers.Savers
if (video != null)
{
AddChapters(video, builder, itemRepository);
//AddChapters(video, builder, itemRepository);
}
}
}

View File

@ -153,6 +153,15 @@ namespace MediaBrowser.Providers.TV
}
}
public override bool EnforceDontFetchMetadata
{
get
{
// Other providers depend on the xml downloaded here
return false;
}
}
protected override DateTime CompareDate(BaseItem item)
{
var seriesId = item.GetProviderId(MetadataProviders.Tvdb);
@ -440,7 +449,10 @@ namespace MediaBrowser.Providers.TV
if (!string.IsNullOrWhiteSpace(val))
{
item.OfficialRating = val;
if (!item.LockedFields.Contains(MetadataFields.OfficialRating))
{
item.OfficialRating = val;
}
}
break;
}

View File

@ -107,13 +107,10 @@ namespace MediaBrowser.Server.Implementations.Dto
.ToArray();
}
if (fields.Contains(ItemFields.ItemCounts))
var itemByName = item as IItemByName;
if (itemByName != null)
{
var itemByName = item as IItemByName;
if (itemByName != null)
{
AttachItemByNameCounts(dto, itemByName, user);
}
AttachItemByNameCounts(dto, itemByName, user);
}
return dto;
@ -166,18 +163,13 @@ namespace MediaBrowser.Server.Implementations.Dto
{
if (item.IsFolder)
{
var hasItemCounts = fields.Contains(ItemFields.ItemCounts);
var folder = (Folder)item;
if (hasItemCounts || fields.Contains(ItemFields.CumulativeRunTimeTicks))
dto.ChildCount = folder.GetChildren(user, true).Count();
if (!(folder is UserRootFolder))
{
var folder = (Folder)item;
if (hasItemCounts)
{
dto.ChildCount = folder.GetChildren(user, true).Count();
}
SetSpecialCounts(folder, user, dto);
SetSpecialCounts(folder, user, dto, fields);
}
}
@ -1068,8 +1060,9 @@ namespace MediaBrowser.Server.Implementations.Dto
/// <param name="folder">The folder.</param>
/// <param name="user">The user.</param>
/// <param name="dto">The dto.</param>
/// <param name="fields">The fields.</param>
/// <returns>Task.</returns>
private void SetSpecialCounts(Folder folder, User user, BaseItemDto dto)
private void SetSpecialCounts(Folder folder, User user, BaseItemDto dto, List<ItemFields> fields)
{
var rcentlyAddedItemCount = 0;
var recursiveItemCount = 0;
@ -1127,7 +1120,7 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount;
}
if (runtime > 0)
if (runtime > 0 && fields.Contains(ItemFields.CumulativeRunTimeTicks))
{
dto.CumulativeRunTimeTicks = runtime;
}

View File

@ -356,6 +356,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer
try
{
ProcessRequest(context);
var url = context.Request.Url.ToString();
var endPoint = context.Request.RemoteEndPoint;
LogResponse(context, url, endPoint);
}
catch (Exception ex)
{
@ -433,9 +439,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
var httpRes = new HttpListenerResponseWrapper(context.Response);
var handler = ServiceStackHttpHandlerFactory.GetHandler(httpReq);
var url = context.Request.Url.ToString();
var endPoint = context.Request.RemoteEndPoint;
var serviceStackHandler = handler as IServiceStackHttpHandler;
if (serviceStackHandler != null)
@ -446,7 +449,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
httpReq.OperationName = operationName = restHandler.RestPath.RequestType.Name;
}
serviceStackHandler.ProcessRequest(httpReq, httpRes, operationName);
LogResponse(context, url, endPoint);
return;
}

View File

@ -49,21 +49,21 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
</Reference>
<Reference Include="ServiceStack, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.3.9.59\lib\net35\ServiceStack.dll</HintPath>
<HintPath>..\packages\ServiceStack.3.9.62\lib\net35\ServiceStack.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Api.Swagger, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Api.Swagger.3.9.59\lib\net35\ServiceStack.Api.Swagger.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Common, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.Common, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Common.dll</HintPath>
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Interfaces, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.Interfaces, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Interfaces.dll</HintPath>
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.OrmLite.SqlServer, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@ -73,13 +73,13 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Redis.3.9.43\lib\net35\ServiceStack.Redis.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.ServiceInterface, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.ServiceInterface, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.3.9.59\lib\net35\ServiceStack.ServiceInterface.dll</HintPath>
<HintPath>..\packages\ServiceStack.3.9.62\lib\net35\ServiceStack.ServiceInterface.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Text.3.9.59\lib\net35\ServiceStack.Text.dll</HintPath>
<HintPath>..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@ -254,10 +254,8 @@
<EmbeddedResource Include="Localization\Ratings\kz.txt" />
<EmbeddedResource Include="Localization\Ratings\nz.txt" />
<EmbeddedResource Include="Localization\Ratings\ru.txt" />
<EmbeddedResource Include="MediaEncoder\readme.txt" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MediaEncoder\ffmpeg20130904.zip" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>

View File

@ -1,9 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
@ -13,7 +11,6 @@ using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
@ -26,12 +23,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// </summary>
public class MediaEncoder : IMediaEncoder, IDisposable
{
/// <summary>
/// Gets or sets the zip client.
/// </summary>
/// <value>The zip client.</value>
private readonly IZipClient _zipClient;
/// <summary>
/// The _logger
/// </summary>
@ -48,8 +39,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// <value>The json serializer.</value>
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
/// <summary>
/// The video image resource pool
/// </summary>
@ -70,50 +59,25 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
/// </summary>
private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(2, 2);
/// <summary>
/// Gets or sets the versioned directory path.
/// </summary>
/// <value>The versioned directory path.</value>
private string VersionedDirectoryPath { get; set; }
public string FFMpegPath { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="MediaEncoder" /> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="zipClient">The zip client.</param>
/// <param name="appPaths">The app paths.</param>
/// <param name="jsonSerializer">The json serializer.</param>
public MediaEncoder(ILogger logger, IZipClient zipClient, IApplicationPaths appPaths,
IJsonSerializer jsonSerializer, IHttpClient httpClient)
public string FFProbePath { get; private set; }
public string Version { get; private set; }
public MediaEncoder(ILogger logger, IApplicationPaths appPaths,
IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version)
{
_logger = logger;
_zipClient = zipClient;
_appPaths = appPaths;
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
Version = version;
FFProbePath = ffProbePath;
FFMpegPath = ffMpegPath;
// Not crazy about this but it's the only way to suppress ffmpeg crash dialog boxes
SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT |
ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX);
Task.Run(() => VersionedDirectoryPath = GetVersionedDirectoryPath());
}
/// <summary>
/// Gets the media tools path.
/// </summary>
/// <param name="create">if set to <c>true</c> [create].</param>
/// <returns>System.String.</returns>
private string GetMediaToolsPath(bool create)
{
var path = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg");
if (create && !Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return path;
}
/// <summary>
@ -125,182 +89,6 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
get { return FFMpegPath; }
}
/// <summary>
/// The _ FF MPEG path
/// </summary>
private string _FFMpegPath;
/// <summary>
/// Gets the path to ffmpeg.exe
/// </summary>
/// <value>The FF MPEG path.</value>
public string FFMpegPath
{
get { return _FFMpegPath ?? (_FFMpegPath = Path.Combine(VersionedDirectoryPath, "ffmpeg.exe")); }
}
/// <summary>
/// The _ FF probe path
/// </summary>
private string _FFProbePath;
/// <summary>
/// Gets the path to ffprobe.exe
/// </summary>
/// <value>The FF probe path.</value>
private string FFProbePath
{
get { return _FFProbePath ?? (_FFProbePath = Path.Combine(VersionedDirectoryPath, "ffprobe.exe")); }
}
/// <summary>
/// Gets the version.
/// </summary>
/// <value>The version.</value>
public string Version
{
get { return Path.GetFileNameWithoutExtension(VersionedDirectoryPath); }
}
/// <summary>
/// Gets the versioned directory path.
/// </summary>
/// <returns>System.String.</returns>
private string GetVersionedDirectoryPath()
{
var assembly = GetType().Assembly;
var prefix = GetType().Namespace + ".";
var srch = prefix + "ffmpeg";
var resource = assembly.GetManifestResourceNames().First(r => r.StartsWith(srch));
var filename =
resource.Substring(resource.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) + prefix.Length);
var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true),
Path.GetFileNameWithoutExtension(filename));
if (!Directory.Exists(versionedDirectoryPath))
{
Directory.CreateDirectory(versionedDirectoryPath);
}
ExtractTools(assembly, resource, versionedDirectoryPath);
return versionedDirectoryPath;
}
/// <summary>
/// Extracts the tools.
/// </summary>
/// <param name="assembly">The assembly.</param>
/// <param name="zipFileResourcePath">The zip file resource path.</param>
/// <param name="targetPath">The target path.</param>
private async void ExtractTools(Assembly assembly, string zipFileResourcePath, string targetPath)
{
using (var resourceStream = assembly.GetManifestResourceStream(zipFileResourcePath))
{
_zipClient.ExtractAll(resourceStream, targetPath, false);
}
try
{
await DownloadFonts(targetPath).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error getting ffmpeg font files", ex);
}
}
private const string FontUrl = "https://www.dropbox.com/s/9nb76tybcsw5xrk/ARIALUNI.zip?dl=1";
/// <summary>
/// Extracts the fonts.
/// </summary>
/// <param name="targetPath">The target path.</param>
private async Task DownloadFonts(string targetPath)
{
var fontsDirectory = Path.Combine(targetPath, "fonts");
if (!Directory.Exists(fontsDirectory))
{
Directory.CreateDirectory(fontsDirectory);
}
const string fontFilename = "ARIALUNI.TTF";
var fontFile = Path.Combine(fontsDirectory, fontFilename);
if (!File.Exists(fontFile))
{
await DownloadFontFile(fontsDirectory, fontFilename).ConfigureAwait(false);
}
await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
}
private async Task DownloadFontFile(string fontsDirectory, string fontFilename)
{
var existingFile = Directory
.EnumerateFiles(_appPaths.ProgramDataPath, fontFilename, SearchOption.AllDirectories)
.FirstOrDefault();
if (existingFile != null)
{
try
{
File.Copy(existingFile, Path.Combine(fontsDirectory, fontFilename), true);
return;
}
catch (IOException ex)
{
// Log this, but don't let it fail the operation
_logger.ErrorException("Error copying file", ex);
}
}
var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
{
Url = FontUrl,
Progress = new Progress<double>()
});
_zipClient.ExtractAll(tempFile, fontsDirectory, true);
try
{
File.Delete(tempFile);
}
catch (IOException ex)
{
// Log this, but don't let it fail the operation
_logger.ErrorException("Error deleting temp file {0}", ex, tempFile);
}
}
private async Task WriteFontConfigFile(string fontsDirectory)
{
const string fontConfigFilename = "fonts.conf";
var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename);
if (!File.Exists(fontConfigFile))
{
var contents = string.Format("<?xml version=\"1.0\"?><fontconfig><dir>{0}</dir><alias><family>Arial</family><prefer>Arial Unicode MS</prefer></alias></fontconfig>", fontsDirectory);
var bytes = Encoding.UTF8.GetBytes(contents);
using (var fileStream = new FileStream(fontConfigFile, FileMode.Create, FileAccess.Write,
FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize,
FileOptions.Asynchronous))
{
await fileStream.WriteAsync(bytes, 0, bytes.Length);
}
}
}
/// <summary>
/// Gets the media info.
/// </summary>

View File

@ -128,7 +128,7 @@ namespace MediaBrowser.Server.Implementations.Providers
// Put this check below the await because the needs refresh of the next tier of providers may depend on the previous ones running
// This is the case for the fan art provider which depends on the movie and tv providers having run before them
if (provider.RequiresInternet && item.DontFetchMeta)
if (provider.RequiresInternet && item.DontFetchMeta && provider.EnforceDontFetchMetadata)
{
continue;
}

View File

@ -1,4 +1,5 @@
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Common;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Common.Updates;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
@ -23,15 +24,13 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
private readonly IInstallationManager _installationManager;
/// <summary>
/// Initializes a new instance of the <see cref="PluginUpdateTask" /> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="installationManager">The installation manager.</param>
public PluginUpdateTask(ILogger logger, IInstallationManager installationManager)
private readonly IApplicationHost _appHost;
public PluginUpdateTask(ILogger logger, IInstallationManager installationManager, IApplicationHost appHost)
{
_logger = logger;
_installationManager = installationManager;
_appHost = appHost;
}
/// <summary>
@ -60,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
{
progress.Report(0);
var packagesToInstall = (await _installationManager.GetAvailablePluginUpdates(true, cancellationToken).ConfigureAwait(false)).ToList();
var packagesToInstall = (await _installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, true, cancellationToken).ConfigureAwait(false)).ToList();
progress.Report(10);

View File

@ -7,12 +7,12 @@
<package id="Rx-Core" version="2.1.30214.0" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.1.30214.0" targetFramework="net45" />
<package id="Rx-Linq" version="2.1.30214.0" targetFramework="net45" />
<package id="ServiceStack" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack" version="3.9.62" targetFramework="net45" />
<package id="ServiceStack.Api.Swagger" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" />
<package id="ServiceStack.OrmLite.SqlServer" version="3.9.43" targetFramework="net45" />
<package id="ServiceStack.Redis" version="3.9.43" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" />
<package id="SharpZipLib" version="0.86.0" targetFramework="net45" />
<package id="System.Data.SQLite.x86" version="1.0.88.0" targetFramework="net45" />
</packages>

View File

@ -20,7 +20,7 @@
$(function () {
window.swaggerUi = new SwaggerUi({
discoveryUrl: "../resources",
apiKey: "special-key",
apiKey:"special-key",
dom_id:"swagger-ui-container",
supportHeaderParams: false,
supportedSubmitMethods: ['get', 'post', 'put'],

View File

@ -60,7 +60,6 @@ using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace MediaBrowser.ServerApplication
{
@ -285,8 +284,7 @@ namespace MediaBrowser.ServerApplication
RegisterSingleInstance<ILibrarySearchEngine>(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager));
MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ZipClient, ApplicationPaths, JsonSerializer, HttpClient);
RegisterSingleInstance(MediaEncoder);
await RegisterMediaEncoder().ConfigureAwait(false);
var clientConnectionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository);
RegisterSingleInstance<ISessionManager>(clientConnectionManager);
@ -317,6 +315,18 @@ namespace MediaBrowser.ServerApplication
SetKernelProperties();
}
/// <summary>
/// Registers the media encoder.
/// </summary>
/// <returns>Task.</returns>
private async Task RegisterMediaEncoder()
{
var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient).GetFFMpegInfo().ConfigureAwait(false);
MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.Path, info.ProbePath, info.Version);
RegisterSingleInstance(MediaEncoder);
}
/// <summary>
/// Sets the kernel properties.
/// </summary>
@ -708,7 +718,7 @@ namespace MediaBrowser.ServerApplication
{
var availablePackages = await InstallationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, Constants.MbServerPkgName, ConfigurationManager.CommonConfiguration.SystemUpdateLevel);
var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, Constants.MbServerPkgName, ApplicationVersion, ConfigurationManager.CommonConfiguration.SystemUpdateLevel);
return version != null ? new CheckForUpdateResult { AvailableVersion = version.version, IsUpdateAvailable = version.version > ApplicationVersion, Package = version } :
new CheckForUpdateResult { AvailableVersion = ApplicationVersion, IsUpdateAvailable = false };

View File

@ -0,0 +1,205 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace MediaBrowser.ServerApplication.Implementations
{
public class FFMpegDownloader
{
private readonly IZipClient _zipClient;
private readonly IHttpClient _httpClient;
private readonly IApplicationPaths _appPaths;
private readonly ILogger _logger;
public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient)
{
_logger = logger;
_appPaths = appPaths;
_httpClient = httpClient;
_zipClient = zipClient;
}
public async Task<FFMpegInfo> GetFFMpegInfo()
{
var assembly = GetType().Assembly;
var prefix = GetType().Namespace + ".";
var srch = prefix + "ffmpeg";
var resource = assembly.GetManifestResourceNames().First(r => r.StartsWith(srch));
var filename =
resource.Substring(resource.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) + prefix.Length);
var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true),
Path.GetFileNameWithoutExtension(filename));
if (!Directory.Exists(versionedDirectoryPath))
{
Directory.CreateDirectory(versionedDirectoryPath);
}
await ExtractTools(assembly, resource, versionedDirectoryPath).ConfigureAwait(false);
return new FFMpegInfo
{
ProbePath = Path.Combine(versionedDirectoryPath, "ffprobe.exe"),
Path = Path.Combine(versionedDirectoryPath, "ffmpeg.exe"),
Version = Path.GetFileNameWithoutExtension(versionedDirectoryPath)
};
}
/// <summary>
/// Extracts the tools.
/// </summary>
/// <param name="assembly">The assembly.</param>
/// <param name="zipFileResourcePath">The zip file resource path.</param>
/// <param name="targetPath">The target path.</param>
private async Task ExtractTools(Assembly assembly, string zipFileResourcePath, string targetPath)
{
using (var resourceStream = assembly.GetManifestResourceStream(zipFileResourcePath))
{
_zipClient.ExtractAll(resourceStream, targetPath, false);
}
try
{
await DownloadFonts(targetPath).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error getting ffmpeg font files", ex);
}
}
private const string FontUrl = "https://www.dropbox.com/s/9nb76tybcsw5xrk/ARIALUNI.zip?dl=1";
/// <summary>
/// Extracts the fonts.
/// </summary>
/// <param name="targetPath">The target path.</param>
private async Task DownloadFonts(string targetPath)
{
var fontsDirectory = Path.Combine(targetPath, "fonts");
if (!Directory.Exists(fontsDirectory))
{
Directory.CreateDirectory(fontsDirectory);
}
const string fontFilename = "ARIALUNI.TTF";
var fontFile = Path.Combine(fontsDirectory, fontFilename);
if (!File.Exists(fontFile))
{
await DownloadFontFile(fontsDirectory, fontFilename).ConfigureAwait(false);
}
await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
}
/// <summary>
/// Downloads the font file.
/// </summary>
/// <param name="fontsDirectory">The fonts directory.</param>
/// <param name="fontFilename">The font filename.</param>
/// <returns>Task.</returns>
private async Task DownloadFontFile(string fontsDirectory, string fontFilename)
{
var existingFile = Directory
.EnumerateFiles(_appPaths.ProgramDataPath, fontFilename, SearchOption.AllDirectories)
.FirstOrDefault();
if (existingFile != null)
{
try
{
File.Copy(existingFile, Path.Combine(fontsDirectory, fontFilename), true);
return;
}
catch (IOException ex)
{
// Log this, but don't let it fail the operation
_logger.ErrorException("Error copying file", ex);
}
}
var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
{
Url = FontUrl,
Progress = new Progress<double>()
});
_zipClient.ExtractAll(tempFile, fontsDirectory, true);
try
{
File.Delete(tempFile);
}
catch (IOException ex)
{
// Log this, but don't let it fail the operation
_logger.ErrorException("Error deleting temp file {0}", ex, tempFile);
}
}
/// <summary>
/// Writes the font config file.
/// </summary>
/// <param name="fontsDirectory">The fonts directory.</param>
/// <returns>Task.</returns>
private async Task WriteFontConfigFile(string fontsDirectory)
{
const string fontConfigFilename = "fonts.conf";
var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename);
if (!File.Exists(fontConfigFile))
{
var contents = string.Format("<?xml version=\"1.0\"?><fontconfig><dir>{0}</dir><alias><family>Arial</family><prefer>Arial Unicode MS</prefer></alias></fontconfig>", fontsDirectory);
var bytes = Encoding.UTF8.GetBytes(contents);
using (var fileStream = new FileStream(fontConfigFile, FileMode.Create, FileAccess.Write,
FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize,
FileOptions.Asynchronous))
{
await fileStream.WriteAsync(bytes, 0, bytes.Length);
}
}
}
/// <summary>
/// Gets the media tools path.
/// </summary>
/// <param name="create">if set to <c>true</c> [create].</param>
/// <returns>System.String.</returns>
private string GetMediaToolsPath(bool create)
{
var path = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg");
if (create && !Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return path;
}
}
public class FFMpegInfo
{
public string Path { get; set; }
public string ProbePath { get; set; }
public string Version { get; set; }
}
}

View File

@ -142,17 +142,17 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.IsoMounting.3.0.56\lib\net45\pfmclrapi.dll</HintPath>
</Reference>
<Reference Include="ServiceStack, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.3.9.59\lib\net35\ServiceStack.dll</HintPath>
<HintPath>..\packages\ServiceStack.3.9.62\lib\net35\ServiceStack.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Common, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.Common, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Common.dll</HintPath>
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Interfaces, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.Interfaces, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Interfaces.dll</HintPath>
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.OrmLite.SqlServer">
<HintPath>..\packages\ServiceStack.OrmLite.SqlServer.3.9.44\lib\ServiceStack.OrmLite.SqlServer.dll</HintPath>
@ -160,13 +160,13 @@
<Reference Include="ServiceStack.Redis">
<HintPath>..\packages\ServiceStack.Redis.3.9.44\lib\net35\ServiceStack.Redis.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.ServiceInterface, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.ServiceInterface, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.3.9.59\lib\net35\ServiceStack.ServiceInterface.dll</HintPath>
<HintPath>..\packages\ServiceStack.3.9.62\lib\net35\ServiceStack.ServiceInterface.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Text.3.9.59\lib\net35\ServiceStack.Text.dll</HintPath>
<HintPath>..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="SimpleInjector, Version=2.3.5.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@ -210,6 +210,7 @@
</Compile>
<Compile Include="EntryPoints\StartupWizard.cs" />
<Compile Include="EntryPoints\UdpServerEntryPoint.cs" />
<Compile Include="Implementations\FFMpegDownloader.cs" />
<Compile Include="MainStartup.cs" />
<Compile Include="BackgroundServiceInstaller.cs">
<SubType>Component</SubType>
@ -277,6 +278,7 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.manifest" />
<EmbeddedResource Include="Implementations\ffmpeg20130904.zip" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
@ -388,6 +390,9 @@
<ItemGroup>
<Resource Include="Resources\Images\mb3logo800.png" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Implementations\readme.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>if $(ConfigurationName) == Release (

View File

@ -6,11 +6,11 @@
<package id="MediaBrowser.IsoMounting" version="3.0.56" targetFramework="net45" />
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
<package id="NLog" version="2.0.1.2" targetFramework="net45" />
<package id="ServiceStack" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack" version="3.9.62" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" />
<package id="ServiceStack.OrmLite.SqlServer" version="3.9.44" targetFramework="net45" />
<package id="ServiceStack.Redis" version="3.9.44" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" />
<package id="SimpleInjector" version="2.3.5" targetFramework="net45" />
<package id="System.Data.SQLite.x86" version="1.0.88.0" targetFramework="net45" />
</packages>

View File

@ -35,17 +35,17 @@
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="ServiceStack.Common, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.Common, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Common.dll</HintPath>
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Interfaces, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="ServiceStack.Interfaces, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Interfaces.dll</HintPath>
<HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ServiceStack.Text.3.9.59\lib\net35\ServiceStack.Text.dll</HintPath>
<HintPath>..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.175" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.59" targetFramework="net45" />
<package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" />
<package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" />
</packages>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
<version>3.0.205</version>
<version>3.0.206</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.205" />
<dependency id="MediaBrowser.Common" version="3.0.206" />
<dependency id="NLog" version="2.0.1.2" />
<dependency id="ServiceStack.Text" version="3.9.58" />
<dependency id="SimpleInjector" version="2.3.2" />

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
<version>3.0.205</version>
<version>3.0.206</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
<version>3.0.205</version>
<version>3.0.206</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.205" />
<dependency id="MediaBrowser.Common" version="3.0.206" />
</dependencies>
</metadata>
<files>