diff options
61 files changed, 1254 insertions, 438 deletions
diff --git a/MediaBrowser.Api/GamesService.cs b/MediaBrowser.Api/GamesService.cs index d3b7cbe41..eabda673a 100644 --- a/MediaBrowser.Api/GamesService.cs +++ b/MediaBrowser.Api/GamesService.cs @@ -155,11 +155,11 @@ namespace MediaBrowser.Api var games = items.OfType<Game>().ToList(); - summary.ClientInstalledGameCount = games.Count(i => !i.IsInstalledOnClient); + summary.ClientInstalledGameCount = games.Count(i => !i.IsPlaceHolder); summary.GameCount = games.Count; - summary.GameFileExtensions = games.Where(i => !i.IsInstalledOnClient).Select(i => Path.GetExtension(i.Path)) + summary.GameFileExtensions = games.Where(i => !i.IsPlaceHolder).Select(i => Path.GetExtension(i.Path)) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs new file mode 100644 index 000000000..a32a1ad03 --- /dev/null +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -0,0 +1,289 @@ +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using ServiceStack; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Api +{ + [Route("/Items/{Id}/ExternalIdInfos", "GET")] + [Api(Description = "Gets external id infos for an item")] + public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>> + { + /// <summary> + /// Gets or sets the id. + /// </summary> + /// <value>The id.</value> + [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] + public string Id { get; set; } + } + + [Route("/Items/RemoteSearch/Movie", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>> + { + } + + [Route("/Items/RemoteSearch/Trailer", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>> + { + } + + [Route("/Items/RemoteSearch/AdultVideo", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetAdultVideoRemoteSearchResults : RemoteSearchQuery<ItemLookupInfo>, IReturn<List<RemoteSearchResult>> + { + } + + [Route("/Items/RemoteSearch/Series", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetSeriesRemoteSearchResults : RemoteSearchQuery<SeriesInfo>, IReturn<List<RemoteSearchResult>> + { + } + + [Route("/Items/RemoteSearch/Game", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetGameRemoteSearchResults : RemoteSearchQuery<GameInfo>, IReturn<List<RemoteSearchResult>> + { + } + + [Route("/Items/RemoteSearch/BoxSet", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetBoxSetRemoteSearchResults : RemoteSearchQuery<BoxSetInfo>, IReturn<List<RemoteSearchResult>> + { + } + + [Route("/Items/RemoteSearch/Person", "POST")] + [Api(Description = "Gets external id infos for an item")] + public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>> + { + } + + [Route("/Items/RemoteSearch/Image", "GET")] + [Api(Description = "Gets a remote image")] + public class GetRemoteSearchImage + { + [ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string ImageUrl { get; set; } + + [ApiMember(Name = "ProviderName", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string ProviderName { get; set; } + } + + [Route("/Items/RemoteSearch/Apply/{Id}", "POST")] + [Api(Description = "Applies search criteria to an item and refreshes metadata")] + public class ApplySearchCriteria : RemoteSearchResult, IReturnVoid + { + [ApiMember(Name = "Id", Description = "The item id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + public string Id { get; set; } + } + + public class ItemLookupService : BaseApiService + { + private readonly IDtoService _dtoService; + private readonly IProviderManager _providerManager; + private readonly IServerApplicationPaths _appPaths; + private readonly IFileSystem _fileSystem; + private readonly ILibraryManager _libraryManager; + + public ItemLookupService(IDtoService dtoService, IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem, ILibraryManager libraryManager) + { + _dtoService = dtoService; + _providerManager = providerManager; + _appPaths = appPaths; + _fileSystem = fileSystem; + _libraryManager = libraryManager; + } + + public object Get(GetExternalIdInfos request) + { + var item = _dtoService.GetItemByDtoId(request.Id); + + var infos = _providerManager.GetExternalIdInfos(item).ToList(); + + return ToOptimizedResult(infos); + } + + public object Post(GetMovieRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<Movie, MovieInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + + public object Post(GetAdultVideoRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<AdultVideo, ItemLookupInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + + public object Post(GetSeriesRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<Series, SeriesInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + + public object Post(GetGameRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<Game, GameInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + + public object Post(GetBoxSetRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<BoxSet, BoxSetInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + + public object Post(GetPersonRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<Person, PersonLookupInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + + public object Post(GetTrailerRemoteSearchResults request) + { + var result = _providerManager.GetRemoteSearchResults<Trailer, TrailerInfo>(request, CancellationToken.None).Result; + + return ToOptimizedResult(result); + } + + public object Get(GetRemoteSearchImage request) + { + var result = GetRemoteImage(request).Result; + + return result; + } + + public void Post(ApplySearchCriteria request) + { + var item = _libraryManager.GetItemById(new Guid(request.Id)); + + foreach (var key in request.ProviderIds) + { + var value = key.Value; + + if (!string.IsNullOrWhiteSpace(value)) + { + item.SetProviderId(key.Key, value); + } + } + + var task = item.RefreshMetadata(new MetadataRefreshOptions + { + MetadataRefreshMode = MetadataRefreshMode.FullRefresh, + ImageRefreshMode = ImageRefreshMode.FullRefresh, + ReplaceAllMetadata = true + + }, CancellationToken.None); + + Task.WaitAll(task); + } + + /// <summary> + /// Gets the remote image. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>Task{System.Object}.</returns> + private async Task<object> GetRemoteImage(GetRemoteSearchImage request) + { + var urlHash = request.ImageUrl.GetMD5(); + var pointerCachePath = GetFullCachePath(urlHash.ToString()); + + string contentPath; + + try + { + using (var reader = new StreamReader(pointerCachePath)) + { + contentPath = await reader.ReadToEndAsync().ConfigureAwait(false); + } + + if (File.Exists(contentPath)) + { + return ToStaticFileResult(contentPath); + } + } + catch (DirectoryNotFoundException) + { + // Means the file isn't cached yet + } + catch (FileNotFoundException) + { + // Means the file isn't cached yet + } + + await DownloadImage(request.ProviderName, request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false); + + // Read the pointer file again + using (var reader = new StreamReader(pointerCachePath)) + { + contentPath = await reader.ReadToEndAsync().ConfigureAwait(false); + } + + return ToStaticFileResult(contentPath); + } + + /// <summary> + /// Downloads the image. + /// </summary> + /// <param name="providerName">Name of the provider.</param> + /// <param name="url">The URL.</param> + /// <param name="urlHash">The URL hash.</param> + /// <param name="pointerCachePath">The pointer cache path.</param> + /// <returns>Task.</returns> + private async Task DownloadImage(string providerName, string url, Guid urlHash, string pointerCachePath) + { + var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false); + + var ext = result.ContentType.Split('/').Last(); + + var fullCachePath = GetFullCachePath(urlHash + "." + ext); + + Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + using (var stream = result.Content) + { + using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true)) + { + await stream.CopyToAsync(filestream).ConfigureAwait(false); + } + } + + Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + using (var writer = new StreamWriter(pointerCachePath)) + { + await writer.WriteAsync(fullCachePath).ConfigureAwait(false); + } + } + + /// <summary> + /// Gets the full cache path. + /// </summary> + /// <param name="filename">The filename.</param> + /// <returns>System.String.</returns> + private string GetFullCachePath(string filename) + { + return Path.Combine(_appPaths.CachePath, "remote-images", filename.Substring(0, 1), filename); + } + + } +} diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 4cb20273f..c3fdbb9a0 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -6,10 +6,8 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Providers; using MediaBrowser.Model.Querying; using ServiceStack; using System; @@ -50,18 +48,6 @@ namespace MediaBrowser.Api.Library public int Index { get; set; } } - [Route("/Items/{Id}/ExternalIdInfos", "GET")] - [Api(Description = "Gets external id infos for an item")] - public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>> - { - /// <summary> - /// Gets or sets the id. - /// </summary> - /// <value>The id.</value> - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - /// <summary> /// Class GetCriticReviews /// </summary> @@ -256,29 +242,18 @@ namespace MediaBrowser.Api.Library private readonly IUserDataManager _userDataManager; private readonly IDtoService _dtoService; - private readonly IProviderManager _providerManager; /// <summary> /// Initializes a new instance of the <see cref="LibraryService" /> class. /// </summary> public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager, - IDtoService dtoService, IUserDataManager userDataManager, IProviderManager providerManager) + IDtoService dtoService, IUserDataManager userDataManager) { _itemRepo = itemRepo; _libraryManager = libraryManager; _userManager = userManager; _dtoService = dtoService; _userDataManager = userDataManager; - _providerManager = providerManager; - } - - public object Get(GetExternalIdInfos request) - { - var item = _dtoService.GetItemByDtoId(request.Id); - - var infos = _providerManager.GetExternalIdInfos(item).ToList(); - - return ToOptimizedResult(infos); } public object Get(GetMediaFolders request) diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index ee2a7eafc..bcc487a5d 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -82,6 +82,7 @@ <Compile Include="Images\ImageService.cs" /> <Compile Include="Images\ImageWriter.cs" /> <Compile Include="InstantMixService.cs" /> + <Compile Include="ItemLookupService.cs" /> <Compile Include="ItemRefreshService.cs" /> <Compile Include="ItemUpdateService.cs" /> <Compile Include="Library\LibraryService.cs" /> diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 5b3221078..c6bcbded8 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -491,6 +491,16 @@ namespace MediaBrowser.Api.Playback return string.Format("{4} -vf \"{0}scale=trunc({1}/2)*2:trunc({2}/2)*2{3}\"", yadifParam, widthParam, heightParam, assSubtitleParam, copyTsParam); } + + // If Max dimensions were supplied + //this makes my brain hurt. For width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size + if (request.MaxWidth.HasValue && request.MaxHeight.HasValue) + { + var MaxwidthParam = request.MaxWidth.Value.ToString(UsCulture); + var MaxheightParam = request.MaxHeight.Value.ToString(UsCulture); + + return string.Format("{4} -vf \"{0}scale=trunc(min(iw\\,{1})/2)*2:trunc(min((iw/dar)\\,{2})/2)*2{3}\"", yadifParam, MaxwidthParam, MaxheightParam, assSubtitleParam, copyTsParam); + } var isH264Output = outputVideoCodec.Equals("libx264", StringComparison.OrdinalIgnoreCase); diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 39cccf28a..4a5b69704 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -220,6 +220,12 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "IsInBoxSet", Description = "Optional filter by items that are in boxsets, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? IsInBoxSet { get; set; } + + [ApiMember(Name = "IsLocked", Description = "Optional filter by items that are locked.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public bool? IsLocked { get; set; } + + [ApiMember(Name = "HasSubtitles", Description = "Optional filter by items that are unidentified by internet metadata providers.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public bool? IsUnidentified { get; set; } } /// <summary> @@ -332,7 +338,7 @@ namespace MediaBrowser.Api.UserLibrary var userId = user == null ? (Guid?)null : user.Id; var item = string.IsNullOrEmpty(request.ParentId) ? - user == null ? (BaseItem)_libraryManager.RootFolder : user.RootFolder : + user == null ? _libraryManager.RootFolder : user.RootFolder : _dtoService.GetItemByDtoId(request.ParentId, userId); // Default list type = children @@ -1019,6 +1025,18 @@ namespace MediaBrowser.Api.UserLibrary items = items.Where(i => i.IsPlayed(user) == val); } + if (request.IsUnidentified.HasValue) + { + var val = request.IsUnidentified.Value; + items = items.Where(i => i.IsUnidentified == val); + } + + if (request.IsLocked.HasValue) + { + var val = request.IsLocked.Value; + items = items.Where(i => i.IsLocked == val); + } + if (request.ParentIndexNumber.HasValue) { var filterValue = request.ParentIndexNumber.Value; diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index 1688fac8b..04b8865c1 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -48,13 +48,13 @@ <RunPostBuildEvent>Always</RunPostBuildEvent> </PropertyGroup> <ItemGroup> - <Reference Include="SimpleInjector, Version=2.4.1.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> + <Reference Include="SimpleInjector, Version=2.5.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\SimpleInjector.2.4.1\lib\net45\SimpleInjector.dll</HintPath> + <HintPath>..\packages\SimpleInjector.2.5.0\lib\net45\SimpleInjector.dll</HintPath> </Reference> - <Reference Include="SimpleInjector.Diagnostics, Version=2.4.1.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> + <Reference Include="SimpleInjector.Diagnostics, Version=2.5.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\SimpleInjector.2.4.1\lib\net45\SimpleInjector.Diagnostics.dll</HintPath> + <HintPath>..\packages\SimpleInjector.2.5.0\lib\net45\SimpleInjector.Diagnostics.dll</HintPath> </Reference> <Reference Include="System" /> <Reference Include="System.Configuration" /> diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config index e04fecc1d..38d6be2ef 100644 --- a/MediaBrowser.Common.Implementations/packages.config +++ b/MediaBrowser.Common.Implementations/packages.config @@ -2,5 +2,5 @@ <packages> <package id="NLog" version="2.1.0" targetFramework="net45" /> <package id="sharpcompress" version="0.10.2" targetFramework="net45" /> - <package id="SimpleInjector" version="2.4.1" targetFramework="net45" /> + <package id="SimpleInjector" version="2.5.0" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 9d520cf6f..923673bd8 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -229,6 +229,8 @@ namespace MediaBrowser.Controller.Entities } } + public bool IsUnidentified { get; set; } + /// <summary> /// Gets or sets the locked fields. /// </summary> diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 2d47cf632..6628ffc23 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -149,7 +149,7 @@ namespace MediaBrowser.Controller.Entities try { - locationsDicionary = PhysicalLocations.Distinct().ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); + locationsDicionary = PhysicalLocations.Distinct(StringComparer.OrdinalIgnoreCase).ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); } catch (IOException ex) { @@ -181,7 +181,7 @@ namespace MediaBrowser.Controller.Entities try { - locationsDicionary = PhysicalLocations.Distinct().ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); + locationsDicionary = PhysicalLocations.Distinct(StringComparer.OrdinalIgnoreCase).ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); } catch (IOException ex) { diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 522bc3a2d..627f657ab 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -352,6 +352,26 @@ namespace MediaBrowser.Controller.Entities return dictionary; } + private bool IsValidFromResolver(BaseItem current, BaseItem newItem) + { + var currentAsPlaceHolder = current as ISupportsPlaceHolders; + + if (currentAsPlaceHolder != null) + { + var newHasPlaceHolder = newItem as ISupportsPlaceHolders; + + if (newHasPlaceHolder != null) + { + if (currentAsPlaceHolder.IsPlaceHolder != newHasPlaceHolder.IsPlaceHolder) + { + return false; + } + } + } + + return current.IsInMixedFolder == newItem.IsInMixedFolder; + } + /// <summary> /// Validates the children internal. /// </summary> @@ -401,7 +421,7 @@ namespace MediaBrowser.Controller.Entities { BaseItem currentChild; - if (currentChildren.TryGetValue(child.Id, out currentChild) && child.IsInMixedFolder == currentChild.IsInMixedFolder) + if (currentChildren.TryGetValue(child.Id, out currentChild) && IsValidFromResolver(currentChild, child)) { var currentChildLocationType = currentChild.LocationType; if (currentChildLocationType != LocationType.Remote && diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index e490a59cd..062bdfa88 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -7,7 +7,7 @@ using System.Linq; namespace MediaBrowser.Controller.Entities { - public class Game : BaseItem, IHasSoundtracks, IHasTrailers, IHasThemeMedia, IHasTags, IHasScreenshots, IHasPreferredMetadataLanguage, IHasLookupInfo<GameInfo> + public class Game : BaseItem, IHasSoundtracks, IHasTrailers, IHasThemeMedia, IHasTags, IHasScreenshots, ISupportsPlaceHolders, IHasPreferredMetadataLanguage, IHasLookupInfo<GameInfo> { public List<Guid> SoundtrackIds { get; set; } @@ -63,10 +63,10 @@ namespace MediaBrowser.Controller.Entities public int? PlayersSupported { get; set; } /// <summary> - /// Gets or sets a value indicating whether this instance is installed on client. + /// Gets a value indicating whether this instance is place holder. /// </summary> - /// <value><c>true</c> if this instance is installed on client; otherwise, <c>false</c>.</value> - public bool IsInstalledOnClient { get; set; } + /// <value><c>true</c> if this instance is place holder; otherwise, <c>false</c>.</value> + public bool IsPlaceHolder { get; set; } /// <summary> /// Gets or sets the game system. diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs index 7182d086a..91f37135f 100644 --- a/MediaBrowser.Controller/Entities/IHasMetadata.cs +++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs @@ -37,12 +37,6 @@ namespace MediaBrowser.Controller.Entities DateTime DateLastSaved { get; set; } /// <summary> - /// Gets a value indicating whether this instance is in mixed folder. - /// </summary> - /// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value> - bool IsInMixedFolder { get; } - - /// <summary> /// Updates to repository. /// </summary> /// <param name="updateReason">The update reason.</param> @@ -55,5 +49,11 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> bool BeforeMetadataRefresh(); + + /// <summary> + /// Gets or sets a value indicating whether this instance is unidentified. + /// </summary> + /// <value><c>true</c> if this instance is unidentified; otherwise, <c>false</c>.</value> + bool IsUnidentified { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/ISupportsPlaceHolders.cs b/MediaBrowser.Controller/Entities/ISupportsPlaceHolders.cs new file mode 100644 index 000000000..2507c8ee6 --- /dev/null +++ b/MediaBrowser.Controller/Entities/ISupportsPlaceHolders.cs @@ -0,0 +1,12 @@ + +namespace MediaBrowser.Controller.Entities +{ + public interface ISupportsPlaceHolders + { + /// <summary> + /// Gets a value indicating whether this instance is place holder. + /// </summary> + /// <value><c>true</c> if this instance is place holder; otherwise, <c>false</c>.</value> + bool IsPlaceHolder { get; } + } +} diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index fa85f0edc..e61e958f5 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -16,7 +16,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class Video /// </summary> - public class Video : BaseItem, IHasMediaStreams, IHasAspectRatio, IHasTags + public class Video : BaseItem, IHasMediaStreams, IHasAspectRatio, IHasTags, ISupportsPlaceHolders { public bool IsMultiPart { get; set; } @@ -42,6 +42,8 @@ namespace MediaBrowser.Controller.Entities /// <value><c>true</c> if this instance has subtitles; otherwise, <c>false</c>.</value> public bool HasSubtitles { get; set; } + public bool IsPlaceHolder { get; set; } + /// <summary> /// Gets or sets the tags. /// </summary> diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs index 82911117f..c64e4fa0c 100644 --- a/MediaBrowser.Controller/Library/TVUtils.cs +++ b/MediaBrowser.Controller/Library/TVUtils.cs @@ -234,9 +234,12 @@ namespace MediaBrowser.Controller.Library { var fullName = child.FullName; - if (EntityResolutionHelper.IsVideoFile(fullName) && GetEpisodeNumberFromFile(fullName, false).HasValue) + if (EntityResolutionHelper.IsVideoFile(fullName) || EntityResolutionHelper.IsVideoPlaceHolder(fullName)) { - return true; + if (GetEpisodeNumberFromFile(fullName, false).HasValue) + { + return true; + } } } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index c07693b36..ff446f2ef 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -105,6 +105,7 @@ <Compile Include="Entities\ILibraryItem.cs" /> <Compile Include="Entities\ImageSourceInfo.cs" /> <Compile Include="Entities\IMetadataContainer.cs" /> + <Compile Include="Entities\ISupportsPlaceHolders.cs" /> <Compile Include="Entities\ItemImageInfo.cs" /> <Compile Include="Entities\LinkedChild.cs" /> <Compile Include="Entities\MusicVideo.cs" /> diff --git a/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs b/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs index c98810cbc..9aed4d921 100644 --- a/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs @@ -14,4 +14,9 @@ namespace MediaBrowser.Controller.Providers { Task<ItemUpdateType> FetchAsync(TItemType item, IDirectoryService directoryService, CancellationToken cancellationToken); } + + public interface IPreRefreshProvider : ICustomMetadataProvider + { + + } } diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 83ee6ae83..94b19498a 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; @@ -126,5 +127,14 @@ namespace MediaBrowser.Controller.Providers CancellationToken cancellationToken) where TItemType : BaseItem, new() where TLookupType : ItemLookupInfo; + + /// <summary> + /// Gets the search image. + /// </summary> + /// <param name="providerName">Name of the provider.</param> + /// <param name="url">The URL.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task{HttpResponseInfo}.</returns> + Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken); } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs b/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs index f00a22a3a..0ff7ee5a9 100644 --- a/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs @@ -18,11 +18,8 @@ namespace MediaBrowser.Controller.Providers Task<MetadataResult<TItemType>> GetMetadata(TLookupInfoType info, CancellationToken cancellationToken); } - public interface IRemoteSearchProvider<in TLookupInfoType> : IMetadataProvider - where TLookupInfoType : ItemLookupInfo + public interface IRemoteSearchProvider : IMetadataProvider { - Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TLookupInfoType searchInfo, CancellationToken cancellationToken); - /// <summary> /// Gets the image response. /// </summary> @@ -31,6 +28,12 @@ namespace MediaBrowser.Controller.Providers /// <returns>Task{HttpResponseInfo}.</returns> Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken); } + + public interface IRemoteSearchProvider<in TLookupInfoType> : IRemoteSearchProvider + where TLookupInfoType : ItemLookupInfo + { + Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TLookupInfoType searchInfo, CancellationToken cancellationToken); + } public class RemoteSearchQuery<T> where T : ItemLookupInfo diff --git a/MediaBrowser.Controller/Resolvers/BaseVideoResolver.cs b/MediaBrowser.Controller/Resolvers/BaseVideoResolver.cs index aadaf5423..9e5d68c48 100644 --- a/MediaBrowser.Controller/Resolvers/BaseVideoResolver.cs +++ b/MediaBrowser.Controller/Resolvers/BaseVideoResolver.cs @@ -35,7 +35,9 @@ namespace MediaBrowser.Controller.Resolvers // If the path is a file check for a matching extensions if (!args.IsDirectory) { - if (EntityResolutionHelper.IsVideoFile(args.Path)) + var isPlaceHolder = EntityResolutionHelper.IsVideoPlaceHolder(args.Path); + + if (EntityResolutionHelper.IsVideoFile(args.Path) || isPlaceHolder) { var extension = Path.GetExtension(args.Path); @@ -46,7 +48,8 @@ namespace MediaBrowser.Controller.Resolvers { VideoType = type, Path = args.Path, - IsInMixedFolder = true + IsInMixedFolder = true, + IsPlaceHolder = isPlaceHolder }; } } diff --git a/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs b/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs index 42b637140..0f93e8e8a 100644 --- a/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs +++ b/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs @@ -140,6 +140,24 @@ namespace MediaBrowser.Controller.Resolvers } /// <summary> + /// Determines whether [is place holder] [the specified path]. + /// </summary> + /// <param name="path">The path.</param> + /// <returns><c>true</c> if [is place holder] [the specified path]; otherwise, <c>false</c>.</returns> + /// <exception cref="System.ArgumentNullException">path</exception> + public static bool IsVideoPlaceHolder(string path) + { + if (string.IsNullOrEmpty(path)) + { + throw new ArgumentNullException("path"); + } + + var extension = Path.GetExtension(path); + + return string.Equals(extension, ".disc", StringComparison.OrdinalIgnoreCase); + } + + /// <summary> /// Ensures DateCreated and DateModified have values /// </summary> /// <param name="fileSystem">The file system.</param> diff --git a/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs b/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs index d86b6650a..b1afeb0f4 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToServerEntryPoint.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Dlna.PlayTo public void Run() { - _manager.Start(); + //_manager.Start(); } #region Dispose diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 1b4a6813e..fc232edb3 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -209,6 +209,8 @@ namespace MediaBrowser.Model.Configuration public bool EnableRealtimeMonitor { get; set; } public PathSubstitution[] PathSubstitutions { get; set; } + public string ServerName { get; set; } + /// <summary> /// Initializes a new instance of the <see cref="ServerConfiguration" /> class. /// </summary> diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 7ba3939a2..9e57f045a 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -48,6 +48,10 @@ namespace MediaBrowser.Model.Dto public string AwardSummary { get; set; } public float? Metascore { get; set; } + + public bool IsUnidentified { get; set; } + + public int? AnimeSeriesIndex { get; set; } /// <summary> /// Gets or sets the DVD season number. @@ -205,6 +209,12 @@ namespace MediaBrowser.Model.Dto public int? Players { get; set; } /// <summary> + /// Gets or sets a value indicating whether this instance is place holder. + /// </summary> + /// <value><c>null</c> if [is place holder] contains no value, <c>true</c> if [is place holder]; otherwise, <c>false</c>.</value> + public bool? IsPlaceHolder { get; set; } + + /// <summary> /// Gets or sets the index number. /// </summary> /// <value>The index number.</value> diff --git a/MediaBrowser.Model/Providers/RemoteSearchResult.cs b/MediaBrowser.Model/Providers/RemoteSearchResult.cs index 122266614..8c9e116d6 100644 --- a/MediaBrowser.Model/Providers/RemoteSearchResult.cs +++ b/MediaBrowser.Model/Providers/RemoteSearchResult.cs @@ -31,6 +31,8 @@ namespace MediaBrowser.Model.Providers public string SearchProviderName { get; set; } + public string GameSystem { get; set; } + public RemoteSearchResult() { ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 24707b29b..ec31c5529 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -147,6 +147,12 @@ namespace MediaBrowser.Model.System public bool SupportsAutoRunAtStartup { get; set; } /// <summary> + /// Gets or sets the name of the server. + /// </summary> + /// <value>The name of the server.</value> + public string ServerName { get; set; } + + /// <summary> /// Initializes a new instance of the <see cref="SystemInfo" /> class. /// </summary> public SystemInfo() diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs index 09939f2d6..29032ca29 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -22,7 +22,6 @@ namespace MediaBrowser.Providers.BoxSets { public class MovieDbBoxSetProvider : IRemoteMetadataProvider<BoxSet, BoxSetInfo> { - private readonly CultureInfo _enUs = new CultureInfo("en-US"); private const string GetCollectionInfo3 = @"http://api.themoviedb.org/3/collection/{0}?api_key={1}&append_to_response=images"; internal static MovieDbBoxSetProvider Current; @@ -32,20 +31,53 @@ namespace MediaBrowser.Providers.BoxSets private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; private readonly ILocalizationManager _localization; + private readonly IHttpClient _httpClient; - public MovieDbBoxSetProvider(ILogger logger, IJsonSerializer json, IServerConfigurationManager config, IFileSystem fileSystem, ILocalizationManager localization) + public MovieDbBoxSetProvider(ILogger logger, IJsonSerializer json, IServerConfigurationManager config, IFileSystem fileSystem, ILocalizationManager localization, IHttpClient httpClient) { _logger = logger; _json = json; _config = config; _fileSystem = fileSystem; _localization = localization; + _httpClient = httpClient; Current = this; } + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(BoxSetInfo searchInfo, CancellationToken cancellationToken) { - return new List<RemoteSearchResult>(); + var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb); + + var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); + + var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + + if (!string.IsNullOrEmpty(tmdbId)) + { + await EnsureInfo(tmdbId, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false); + + var dataFilePath = GetDataFilePath(_config.ApplicationPaths, tmdbId, searchInfo.MetadataLanguage); + var info = _json.DeserializeFromFile<RootObject>(dataFilePath); + + var images = (info.images ?? new Images()).posters ?? new List<Poster>(); + + var result = new RemoteSearchResult + { + Name = info.name, + + SearchProviderName = Name, + + ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path) + }; + + result.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture)); + + return new[] { result }; + } + + return await new MovieDbSearch(_logger, _json).GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false); } public async Task<MetadataResult<BoxSet>> GetMetadata(BoxSetInfo id, CancellationToken cancellationToken) @@ -55,11 +87,13 @@ namespace MediaBrowser.Providers.BoxSets // We don't already have an Id, need to fetch it if (string.IsNullOrEmpty(tmdbId)) { - var searchResult = await new MovieDbSearch(_logger, _json).FindCollectionId(id, cancellationToken).ConfigureAwait(false); + var searchResults = await new MovieDbSearch(_logger, _json).GetSearchResults(id, cancellationToken).ConfigureAwait(false); + + var searchResult = searchResults.FirstOrDefault(); if (searchResult != null) { - tmdbId = searchResult.id.ToString(_enUs); + tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); } } @@ -106,7 +140,7 @@ namespace MediaBrowser.Providers.BoxSets Overview = obj.overview }; - item.SetProviderId(MetadataProviders.Tmdb, obj.id.ToString(_enUs)); + item.SetProviderId(MetadataProviders.Tmdb, obj.id.ToString(_usCulture)); return item; } @@ -219,10 +253,15 @@ namespace MediaBrowser.Providers.BoxSets private static string GetDataFilePath(IApplicationPaths appPaths, string tmdbId, string preferredLanguage) { + if (string.IsNullOrWhiteSpace(preferredLanguage)) + { + throw new ArgumentNullException("preferredLanguage"); + } + var path = GetDataPath(appPaths, tmdbId); var filename = string.Format("all-{0}.json", - preferredLanguage ?? string.Empty); + preferredLanguage); return Path.Combine(path, filename); } @@ -291,7 +330,12 @@ namespace MediaBrowser.Providers.BoxSets public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) { - throw new NotImplementedException(); + return _httpClient.GetResponse(new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = url, + ResourcePool = MovieDbProvider.Current.MovieDbResourcePool + }); } } } diff --git a/MediaBrowser.Providers/Games/GameMetadataService.cs b/MediaBrowser.Providers/Games/GameMetadataService.cs index 1586414ea..1e184bb06 100644 --- a/MediaBrowser.Providers/Games/GameMetadataService.cs +++ b/MediaBrowser.Providers/Games/GameMetadataService.cs @@ -1,25 +1,19 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; namespace MediaBrowser.Providers.Games { public class GameMetadataService : MetadataService<Game, GameInfo> { - private readonly ILibraryManager _libraryManager; - - public GameMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + public GameMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { - _libraryManager = libraryManager; } /// <summary> @@ -38,6 +32,11 @@ namespace MediaBrowser.Providers.Games { target.GameSystem = source.GameSystem; } + + if (replaceData || !target.PlayersSupported.HasValue) + { + target.PlayersSupported = source.PlayersSupported; + } } } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index eb2d7d747..2ecc6c9dd 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -269,6 +269,13 @@ namespace MediaBrowser.Providers.Manager Providers = providers.Select(i => i.GetType().FullName.GetMD5()).ToList() }; + var customProviders = providers.OfType<ICustomMetadataProvider<TItemType>>().ToList(); + + foreach (var provider in customProviders.Where(i => i is IPreRefreshProvider)) + { + await RunCustomProvider(provider, item, options.DirectoryService, refreshResult, cancellationToken).ConfigureAwait(false); + } + var temp = CreateNew(); temp.Path = item.Path; @@ -342,7 +349,7 @@ namespace MediaBrowser.Providers.Manager MergeData(temp, item, item.LockedFields, true, true); } - foreach (var provider in providers.OfType<ICustomMetadataProvider<TItemType>>()) + foreach (var provider in customProviders.Where(i => !(i is IPreRefreshProvider))) { await RunCustomProvider(provider, item, options.DirectoryService, refreshResult, cancellationToken).ConfigureAwait(false); } @@ -379,6 +386,9 @@ namespace MediaBrowser.Providers.Manager { TIdType id = null; + var unidentifiedCount = 0; + var identifiedCount = 0; + foreach (var provider in providers) { var providerName = provider.GetType().Name; @@ -402,9 +412,12 @@ namespace MediaBrowser.Providers.Manager MergeData(result.Item, temp, new List<MetadataFields>(), false, false); refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataDownload; + + identifiedCount++; } else { + unidentifiedCount++; Logger.Debug("{0} returned no metadata for {1}", providerName, item.Path ?? item.Name); } } @@ -414,11 +427,20 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { + unidentifiedCount++; refreshResult.Status = ProviderRefreshStatus.CompletedWithErrors; refreshResult.ErrorMessage = ex.Message; Logger.ErrorException("Error in {0}", ex, provider.Name); } } + + var isUnidentified = unidentifiedCount > 0 && identifiedCount == 0; + + if (item.IsUnidentified != isUnidentified) + { + item.IsUnidentified = isUnidentified; + refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport; + } } private void MergeNewData(TItemType source, TIdType lookupInfo) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 942f414b6..5f6702e74 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -492,7 +492,7 @@ namespace MediaBrowser.Providers.Manager Type = MetadataPluginType.MetadataFetcher })); } - + if (item.IsSaveLocalMetadataEnabled()) { // Savers @@ -657,15 +657,24 @@ namespace MediaBrowser.Providers.Manager providers = providers.Where(i => string.Equals(i.Name, searchInfo.SearchProviderName, StringComparison.OrdinalIgnoreCase)); } + if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataLanguage)) + { + searchInfo.SearchInfo.MetadataLanguage = ConfigurationManager.Configuration.PreferredMetadataLanguage; + } + if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataCountryCode)) + { + searchInfo.SearchInfo.MetadataCountryCode = ConfigurationManager.Configuration.MetadataCountryCode; + } + foreach (var provider in providers) { - var results = await provider.GetSearchResults(searchInfo.SearchInfo, cancellationToken).ConfigureAwait(false); + var results = await GetSearchResults(provider, searchInfo.SearchInfo, cancellationToken).ConfigureAwait(false); var list = results.ToList(); if (list.Count > 0) { - return list; + return list.Take(10); } } @@ -673,6 +682,34 @@ namespace MediaBrowser.Providers.Manager return new List<RemoteSearchResult>(); } + private async Task<IEnumerable<RemoteSearchResult>> GetSearchResults<TLookupType>(IRemoteSearchProvider<TLookupType> provider, TLookupType searchInfo, + CancellationToken cancellationToken) + where TLookupType : ItemLookupInfo + { + var results = await provider.GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false); + + var list = results.ToList(); + + foreach (var item in list) + { + item.SearchProviderName = provider.Name; + } + + return list; + } + + public Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken) + { + var provider = _metadataProviders.OfType<IRemoteSearchProvider>().FirstOrDefault(i => string.Equals(i.Name, providerName, StringComparison.OrdinalIgnoreCase)); + + if (provider == null) + { + throw new ArgumentException("Search provider not found."); + } + + return provider.GetImageResponse(url, cancellationToken); + } + public IEnumerable<IExternalId> GetExternalIds(IHasProviderIds item) { return _externalIds.Where(i => diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index 025945461..8da4919a2 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -58,6 +58,11 @@ namespace MediaBrowser.Providers.Manager target.OfficialRatingDescription = source.OfficialRatingDescription; } + if (replaceData || string.IsNullOrEmpty(target.CustomRating)) + { + target.CustomRating = source.CustomRating; + } + if (!lockedFields.Contains(MetadataFields.Overview)) { if (replaceData || string.IsNullOrEmpty(target.Overview)) diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index bb417536a..55d09b68b 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -126,6 +126,11 @@ namespace MediaBrowser.Providers.MediaInfo return _cachedTask; } + if (item.IsPlaceHolder) + { + return _cachedTask; + } + var prober = new FFProbeVideoInfo(_logger, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager); return prober.ProbeVideo(item, directoryService, cancellationToken); @@ -155,7 +160,7 @@ namespace MediaBrowser.Providers.MediaInfo { var video = item as Video; - if (video != null) + if (video != null && !video.IsPlaceHolder) { var prober = new FFProbeVideoInfo(_logger, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager); diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index 68216c6e1..354758497 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -56,7 +56,7 @@ namespace MediaBrowser.Providers.MediaInfo var video = (Video)item; // No support for this - if (video.VideoType == VideoType.HdDvd) + if (video.VideoType == VideoType.HdDvd || video.IsPlaceHolder) { return Task.FromResult(new DynamicImageResponse { HasImage = false }); } diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs index 9182587b1..f5b43e407 100644 --- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs +++ b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs @@ -380,7 +380,7 @@ namespace MediaBrowser.Providers.Movies /// <returns>System.String.</returns> internal static string GetMoviesDataPath(IApplicationPaths appPaths) { - var dataPath = Path.Combine(appPaths.DataPath, "fanart-movies"); + var dataPath = Path.Combine(appPaths.CachePath, "fanart-movies"); return dataPath; } diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs index abd48e37c..bf2be654b 100644 --- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs +++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs @@ -39,11 +39,13 @@ namespace MediaBrowser.Providers.Movies // Don't search for music video id's because it is very easy to misidentify. if (string.IsNullOrEmpty(tmdbId) && string.IsNullOrEmpty(imdbId) && typeof(T) != typeof(MusicVideo)) { - var searchResult = await new MovieDbSearch(_logger, _jsonSerializer).FindMovieId(itemId, cancellationToken).ConfigureAwait(false); + var searchResults = await new MovieDbSearch(_logger, _jsonSerializer).GetMovieSearchResults(itemId, cancellationToken).ConfigureAwait(false); + + var searchResult = searchResults.FirstOrDefault(); if (searchResult != null) { - tmdbId = searchResult.id.ToString(_usCulture); + tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); } } @@ -174,11 +176,16 @@ namespace MediaBrowser.Providers.Movies : null; } - if (movieData.release_date.Year != 1) + if (!string.IsNullOrWhiteSpace(movieData.release_date)) { - //no specific country release info at all - movie.PremiereDate = movieData.release_date.ToUniversalTime(); - movie.ProductionYear = movieData.release_date.Year; + DateTime r; + + // These dates are always in this exact format + if (DateTime.TryParse(movieData.release_date, _usCulture, DateTimeStyles.None, out r)) + { + movie.PremiereDate = r.ToUniversalTime(); + movie.ProductionYear = movie.PremiereDate.Value.Year; + } } //studios diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 32a77a8a6..05f2d485e 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -12,6 +12,7 @@ using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Threading; @@ -35,6 +36,8 @@ namespace MediaBrowser.Providers.Movies private readonly ILogger _logger; private readonly ILocalizationManager _localization; + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + public MovieDbProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization) { _jsonSerializer = jsonSerializer; @@ -46,9 +49,59 @@ namespace MediaBrowser.Providers.Movies Current = this; } - public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken) + public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken) { - return new List<RemoteSearchResult>(); + return GetMovieSearchResults(searchInfo, cancellationToken); + } + + public async Task<IEnumerable<RemoteSearchResult>> GetMovieSearchResults(ItemLookupInfo searchInfo, CancellationToken cancellationToken) + { + var tmdbSettings = await GetTmdbSettings(cancellationToken).ConfigureAwait(false); + + var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + + var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb); + + if (!string.IsNullOrEmpty(tmdbId)) + { + cancellationToken.ThrowIfCancellationRequested(); + + await EnsureMovieInfo(tmdbId, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false); + + var dataFilePath = GetDataFilePath(tmdbId, searchInfo.MetadataLanguage); + + var obj = _jsonSerializer.DeserializeFromFile<CompleteMovieData>(dataFilePath); + + var remoteResult = new RemoteSearchResult + { + Name = obj.title ?? obj.original_title ?? obj.name, + SearchProviderName = Name, + ImageUrl = string.IsNullOrWhiteSpace(obj.poster_path) ? null : tmdbImageUrl + obj.poster_path + }; + + if (!string.IsNullOrWhiteSpace(obj.release_date)) + { + DateTime r; + + // These dates are always in this exact format + if (DateTime.TryParse(obj.release_date, _usCulture, DateTimeStyles.None, out r)) + { + remoteResult.PremiereDate = r.ToUniversalTime(); + remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year; + } + } + + remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.id.ToString(_usCulture)); + + if (!string.IsNullOrWhiteSpace(obj.imdb_id)) + { + remoteResult.SetProviderId(MetadataProviders.Imdb, obj.imdb_id); + } + + return new[] { remoteResult }; + } + + return await new MovieDbSearch(_logger, _jsonSerializer).GetMovieSearchResults(searchInfo, cancellationToken).ConfigureAwait(false); } public Task<MetadataResult<Movie>> GetMetadata(MovieInfo info, CancellationToken cancellationToken) @@ -57,7 +110,7 @@ namespace MediaBrowser.Providers.Movies } public Task<MetadataResult<T>> GetItemMetadata<T>(ItemLookupInfo id, CancellationToken cancellationToken) - where T : Video, new () + where T : Video, new() { var movieDb = new GenericMovieDbInfo<T>(_logger, _jsonSerializer); @@ -347,10 +400,10 @@ namespace MediaBrowser.Providers.Movies var dataFilePath = GetDataFilePath(tmdbId, item.GetPreferredMetadataLanguage()); var fileInfo = new FileInfo(dataFilePath); - + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; } - + return false; } @@ -530,7 +583,7 @@ namespace MediaBrowser.Providers.Movies public string poster_path { get; set; } public List<ProductionCompany> production_companies { get; set; } public List<ProductionCountry> production_countries { get; set; } - public DateTime release_date { get; set; } + public string release_date { get; set; } public int revenue { get; set; } public int runtime { get; set; } public List<SpokenLanguage> spoken_languages { get; set; } @@ -558,7 +611,12 @@ namespace MediaBrowser.Providers.Movies public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) { - throw new NotImplementedException(); + return _httpClient.GetResponse(new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = url, + ResourcePool = MovieDbResourcePool + }); } } } diff --git a/MediaBrowser.Providers/Movies/MovieDbSearch.cs b/MediaBrowser.Providers/Movies/MovieDbSearch.cs index 383705e0a..500b71a79 100644 --- a/MediaBrowser.Providers/Movies/MovieDbSearch.cs +++ b/MediaBrowser.Providers/Movies/MovieDbSearch.cs @@ -1,6 +1,8 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using System; using System.Collections.Generic; @@ -29,27 +31,31 @@ namespace MediaBrowser.Providers.Movies _json = json; } - public Task<TmdbMovieSearchResult> FindSeriesId(ItemLookupInfo idInfo, CancellationToken cancellationToken) + public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo idInfo, CancellationToken cancellationToken) { - return FindId(idInfo, "tv", cancellationToken); + return GetSearchResults(idInfo, "tv", cancellationToken); } - public Task<TmdbMovieSearchResult> FindMovieId(ItemLookupInfo idInfo, CancellationToken cancellationToken) + public Task<IEnumerable<RemoteSearchResult>> GetMovieSearchResults(ItemLookupInfo idInfo, CancellationToken cancellationToken) { - return FindId(idInfo, "movie", cancellationToken); + return GetSearchResults(idInfo, "movie", cancellationToken); } - public Task<TmdbMovieSearchResult> FindCollectionId(ItemLookupInfo idInfo, CancellationToken cancellationToken) + public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(BoxSetInfo idInfo, CancellationToken cancellationToken) { - return FindId(idInfo, "collection", cancellationToken); + return GetSearchResults(idInfo, "collection", cancellationToken); } - private async Task<TmdbMovieSearchResult> FindId(ItemLookupInfo idInfo, string searchType, CancellationToken cancellationToken) + private async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ItemLookupInfo idInfo, string searchType, CancellationToken cancellationToken) { var name = idInfo.Name; var year = idInfo.Year; int? yearInName = null; + var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); + + var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + NameParser.ParseName(name, out name, out yearInName); year = year ?? yearInName; @@ -60,48 +66,57 @@ namespace MediaBrowser.Providers.Movies //nope - search for it //var searchType = item is BoxSet ? "collection" : "movie"; - var id = await AttemptFindId(name, searchType, year, language, cancellationToken).ConfigureAwait(false); + var results = await GetSearchResults(name, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false); - if (id == null) + if (results.Count == 0) { //try in english if wasn't before - if (language != "en") + if (!string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { - id = await AttemptFindId(name, searchType, year, "en", cancellationToken).ConfigureAwait(false); + results = await GetSearchResults(name, searchType, year, "en", tmdbImageUrl, cancellationToken).ConfigureAwait(false); } - else - { - // try with dot and _ turned to space - var originalName = name; + } - name = name.Replace(",", " "); - name = name.Replace(".", " "); - name = name.Replace("_", " "); - name = name.Replace("-", " "); - name = name.Replace("!", " "); - name = name.Replace("?", " "); + if (results.Count == 0) + { + // try with dot and _ turned to space + var originalName = name; - name = name.Trim(); + name = name.Replace(",", " "); + name = name.Replace(".", " "); + name = name.Replace("_", " "); + name = name.Replace("-", " "); + name = name.Replace("!", " "); + name = name.Replace("?", " "); - // Search again if the new name is different - if (!string.Equals(name, originalName)) - { - id = await AttemptFindId(name, searchType, year, language, cancellationToken).ConfigureAwait(false); + name = name.Trim(); - if (id == null && language != "en") - { - //one more time, in english - id = await AttemptFindId(name, searchType, year, "en", cancellationToken).ConfigureAwait(false); + // Search again if the new name is different + if (!string.Equals(name, originalName)) + { + results = await GetSearchResults(name, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false); + + if (results.Count == 0 && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) + { + //one more time, in english + results = await GetSearchResults(name, searchType, year, "en", tmdbImageUrl, cancellationToken).ConfigureAwait(false); - } } } } - return id; + return results.Where(i => + { + if (year.HasValue && i.ProductionYear.HasValue) + { + return year.Value == i.ProductionYear.Value; + } + + return true; + }); } - private async Task<TmdbMovieSearchResult> AttemptFindId(string name, string type, int? year, string language, CancellationToken cancellationToken) + private async Task<List<RemoteSearchResult>> GetSearchResults(string name, string type, int? year, string language, string baseImageUrl, CancellationToken cancellationToken) { var url3 = string.Format(Search3, WebUtility.UrlEncode(name), ApiKey, language, type); @@ -113,67 +128,62 @@ namespace MediaBrowser.Providers.Movies }).ConfigureAwait(false)) { - var searchResult = _json.DeserializeFromStream<TmdbMovieSearchResults>(json); - return FindBestResult(searchResult.results, name, year); - } - } + var searchResults = _json.DeserializeFromStream<TmdbMovieSearchResults>(json); - private TmdbMovieSearchResult FindBestResult(List<TmdbMovieSearchResult> results, string name, int? year) - { - if (year.HasValue) - { - // Take the first result from the same year - var result = results.FirstOrDefault(i => - { - // Make sure it has a name - if (!string.IsNullOrEmpty(i.title ?? i.name)) + var results = searchResults.results ?? new List<TmdbMovieSearchResult>(); + + var index = 0; + var resultTuples = results.Select(result => new Tuple<TmdbMovieSearchResult, int>(result, index++)).ToList(); + + return resultTuples.OrderBy(i => GetSearchResultOrder(i.Item1, year)) + .ThenBy(i => i.Item2) + .Select(i => i.Item1) + .Select(i => { - DateTime r; + var remoteResult = new RemoteSearchResult + { + SearchProviderName = MovieDbProvider.Current.Name, + Name = i.title ?? i.original_title ?? i.name, + ImageUrl = string.IsNullOrWhiteSpace(i.poster_path) ? null : baseImageUrl + i.poster_path + }; - // These dates are always in this exact format - if (DateTime.TryParseExact(i.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r)) + if (!string.IsNullOrWhiteSpace(i.release_date)) { - return r.Year == year.Value; + DateTime r; + + // These dates are always in this exact format + if (DateTime.TryParseExact(i.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r)) + { + remoteResult.PremiereDate = r.ToUniversalTime(); + remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year; + } } - } - return false; - }); + remoteResult.SetProviderId(MetadataProviders.Tmdb, i.id.ToString(EnUs)); - if (result != null) - { - return result; - } - - // Take the first result within one year - result = results.FirstOrDefault(i => - { - // Make sure it has a name - if (!string.IsNullOrEmpty(i.title ?? i.name)) - { - DateTime r; + return remoteResult; - // These dates are always in this exact format - if (DateTime.TryParseExact(i.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r)) - { - return Math.Abs(r.Year - year.Value) <= 1; - } - } + }) + .ToList(); + } + } - return false; - }); + private int GetSearchResultOrder(TmdbMovieSearchResult result, int? year) + { + if (year.HasValue) + { + DateTime r; - if (result != null) + // These dates are always in this exact format + if (DateTime.TryParseExact(result.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r)) { - return result; + return Math.Abs(r.Year - year.Value); } } - // Just take the first one - return results.FirstOrDefault(i => !string.IsNullOrEmpty(i.title ?? i.name)); + return 0; } - /// <summary> /// Class TmdbMovieSearchResult /// </summary> diff --git a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs index 8c981e2d8..78ea3e99c 100644 --- a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs @@ -11,14 +11,21 @@ namespace MediaBrowser.Providers.Movies { public class MovieDbTrailerProvider : IRemoteMetadataProvider<Trailer, TrailerInfo>, IHasOrder { + private readonly IHttpClient _httpClient; + + public MovieDbTrailerProvider(IHttpClient httpClient) + { + _httpClient = httpClient; + } + public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken) { return MovieDbProvider.Current.GetItemMetadata<Trailer>(info, cancellationToken); } - public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken) + public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken) { - return new List<RemoteSearchResult>(); + return MovieDbProvider.Current.GetMovieSearchResults(searchInfo, cancellationToken); } public string Name @@ -42,7 +49,12 @@ namespace MediaBrowser.Providers.Movies public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) { - throw new NotImplementedException(); + return _httpClient.GetResponse(new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = url, + ResourcePool = MovieDbProvider.Current.MovieDbResourcePool + }); } } } diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs index 270219a2b..b9916dfba 100644 --- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs @@ -458,7 +458,7 @@ namespace MediaBrowser.Providers.Music /// <returns>System.String.</returns> internal static string GetArtistDataPath(IApplicationPaths appPaths) { - var dataPath = Path.Combine(appPaths.DataPath, "fanart-music"); + var dataPath = Path.Combine(appPaths.CachePath, "fanart-music"); return dataPath; } diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs index 792c9e910..b5bf445bf 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs @@ -29,12 +29,14 @@ namespace MediaBrowser.Providers.People private readonly IJsonSerializer _jsonSerializer; private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _configurationManager; + private readonly IHttpClient _httpClient; - public MovieDbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer) + public MovieDbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient) { _fileSystem = fileSystem; _configurationManager = configurationManager; _jsonSerializer = jsonSerializer; + _httpClient = httpClient; Current = this; } @@ -64,6 +66,8 @@ namespace MediaBrowser.Providers.People { Name = info.name, + SearchProviderName = Name, + ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path) }; @@ -94,6 +98,8 @@ namespace MediaBrowser.Providers.People { var result = new RemoteSearchResult { + SearchProviderName = Name, + Name = i.Name, ImageUrl = string.IsNullOrEmpty(i.Profile_Path) ? null : (baseImageUrl + i.Profile_Path) @@ -217,7 +223,7 @@ namespace MediaBrowser.Providers.People private static string GetPersonsDataPath(IApplicationPaths appPaths) { - return Path.Combine(appPaths.DataPath, "tmdb-people"); + return Path.Combine(appPaths.CachePath, "tmdb-people"); } #region Result Objects @@ -349,7 +355,12 @@ namespace MediaBrowser.Providers.People public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) { - throw new NotImplementedException(); + return _httpClient.GetResponse(new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = url, + ResourcePool = MovieDbProvider.Current.MovieDbResourcePool + }); } } } diff --git a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs b/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs index 5f58001ec..e69f2e085 100644 --- a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using System.Globalization; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; @@ -36,6 +37,8 @@ namespace MediaBrowser.Providers.Savers return item is Series && updateType >= ItemUpdateType.MetadataDownload; } + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + /// <summary> /// Saves the specified item. /// </summary> @@ -94,6 +97,11 @@ namespace MediaBrowser.Providers.Savers builder.Append("<FirstAired>" + SecurityElement.Escape(series.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</FirstAired>"); } + if (series.AnimeSeriesIndex.HasValue) + { + builder.Append("<AnimeSeriesIndex>" + SecurityElement.Escape(series.AnimeSeriesIndex.Value.ToString(UsCulture)) + "</AnimeSeriesIndex>"); + } + XmlSaverHelpers.AddCommonNodes(series, builder); builder.Append("</Series>"); @@ -111,7 +119,8 @@ namespace MediaBrowser.Providers.Savers "FirstAired", // Don't preserve old series node - "Series" + "Series", + "AnimeSeriesIndex" }); } diff --git a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanartSeriesProvider.cs index f8fee5e3d..a9554d396 100644 --- a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/FanartSeriesProvider.cs @@ -356,7 +356,7 @@ namespace MediaBrowser.Providers.TV /// <returns>System.String.</returns> internal static string GetSeriesDataPath(IApplicationPaths appPaths) { - var dataPath = Path.Combine(appPaths.DataPath, "fanart-tv"); + var dataPath = Path.Combine(appPaths.CachePath, "fanart-tv"); return dataPath; } diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index c620a6c33..ff8f6a2e6 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -105,12 +105,15 @@ namespace MediaBrowser.Providers.TV hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false); } - var seriesConfig = _config.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, typeof(Series).Name, StringComparison.OrdinalIgnoreCase)); - - if (seriesConfig == null || !seriesConfig.DisabledMetadataFetchers.Contains(TvdbSeriesProvider.Current.Name, StringComparer.OrdinalIgnoreCase)) + if (_config.Configuration.EnableInternetProviders) { - hasNewEpisodes = await AddMissingEpisodes(group.ToList(), seriesDataPath, episodeLookup, cancellationToken) - .ConfigureAwait(false); + var seriesConfig = _config.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, typeof(Series).Name, StringComparison.OrdinalIgnoreCase)); + + if (seriesConfig == null || !seriesConfig.DisabledMetadataFetchers.Contains(TvdbSeriesProvider.Current.Name, StringComparer.OrdinalIgnoreCase)) + { + hasNewEpisodes = await AddMissingEpisodes(group.ToList(), seriesDataPath, episodeLookup, cancellationToken) + .ConfigureAwait(false); + } } if (hasNewSeasons || hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved) diff --git a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs index b46336e90..fc53d4c15 100644 --- a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs @@ -21,7 +21,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.TV { - public class MovieDbSeriesProvider : IRemoteMetadataProvider<Series,SeriesInfo>, IHasOrder + public class MovieDbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder { private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}?api_key={1}&append_to_response=casts,images,keywords,external_ids"; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); @@ -33,14 +33,16 @@ namespace MediaBrowser.Providers.TV private readonly IServerConfigurationManager _configurationManager; private readonly ILogger _logger; private readonly ILocalizationManager _localization; + private readonly IHttpClient _httpClient; - public MovieDbSeriesProvider(IJsonSerializer jsonSerializer, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization) + public MovieDbSeriesProvider(IJsonSerializer jsonSerializer, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization, IHttpClient httpClient) { _jsonSerializer = jsonSerializer; _fileSystem = fileSystem; _configurationManager = configurationManager; _logger = logger; _localization = localization; + _httpClient = httpClient; Current = this; } @@ -51,7 +53,64 @@ namespace MediaBrowser.Providers.TV public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) { - return new List<RemoteSearchResult>(); + var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb); + + if (!string.IsNullOrEmpty(tmdbId)) + { + cancellationToken.ThrowIfCancellationRequested(); + + await EnsureSeriesInfo(tmdbId, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false); + + var dataFilePath = GetDataFilePath(tmdbId, searchInfo.MetadataLanguage); + + var obj = _jsonSerializer.DeserializeFromFile<RootObject>(dataFilePath); + + var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); + var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + + var remoteResult = new RemoteSearchResult + { + Name = obj.name, + SearchProviderName = Name, + ImageUrl = string.IsNullOrWhiteSpace(obj.poster_path) ? null : tmdbImageUrl + obj.poster_path + }; + + remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.id.ToString(_usCulture)); + remoteResult.SetProviderId(MetadataProviders.Imdb, obj.external_ids.imdb_id); + + if (obj.external_ids.tvdb_id > 0) + { + remoteResult.SetProviderId(MetadataProviders.Tvdb, obj.external_ids.tvdb_id.ToString(_usCulture)); + } + + return new[] { remoteResult }; + } + + var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb); + + if (!string.IsNullOrEmpty(imdbId)) + { + var searchResult = await FindByExternalId(imdbId, "imdb_id", cancellationToken).ConfigureAwait(false); + + if (searchResult != null) + { + return new[] { searchResult }; + } + } + + var tvdbId = searchInfo.GetProviderId(MetadataProviders.Tvdb); + + if (!string.IsNullOrEmpty(tvdbId)) + { + var searchResult = await FindByExternalId(tvdbId, "tvdb_id", cancellationToken).ConfigureAwait(false); + + if (searchResult != null) + { + return new[] { searchResult }; + } + } + + return await new MovieDbSearch(_logger, _jsonSerializer).GetSearchResults(searchInfo, cancellationToken).ConfigureAwait(false); } public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken) @@ -66,7 +125,12 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(imdbId)) { - tmdbId = await FindIdByExternalId(imdbId, "imdb_id", cancellationToken).ConfigureAwait(false); + var searchResult = await FindByExternalId(imdbId, "imdb_id", cancellationToken).ConfigureAwait(false); + + if (searchResult != null) + { + tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); + } } } @@ -76,17 +140,24 @@ namespace MediaBrowser.Providers.TV if (!string.IsNullOrEmpty(tvdbId)) { - tmdbId = await FindIdByExternalId(tvdbId, "tvdb_id", cancellationToken).ConfigureAwait(false); + var searchResult = await FindByExternalId(tvdbId, "tvdb_id", cancellationToken).ConfigureAwait(false); + + if (searchResult != null) + { + tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); + } } } if (string.IsNullOrEmpty(tmdbId)) { - var searchResult = await new MovieDbSearch(_logger, _jsonSerializer).FindSeriesId(info, cancellationToken).ConfigureAwait(false); + var searchResults = await new MovieDbSearch(_logger, _jsonSerializer).GetSearchResults(info, cancellationToken).ConfigureAwait(false); + + var searchResult = searchResults.FirstOrDefault(); if (searchResult != null) { - tmdbId = searchResult.id.ToString(_usCulture); + tmdbId = searchResult.GetProviderId(MetadataProviders.Tmdb); } } @@ -98,7 +169,7 @@ namespace MediaBrowser.Providers.TV result.HasMetadata = result.Item != null; } - + return result; } @@ -119,7 +190,7 @@ namespace MediaBrowser.Providers.TV tmdbId = seriesInfo.id.ToString(_usCulture); - dataFilePath = MovieDbProvider.Current.GetDataFilePath(tmdbId, language); + dataFilePath = GetDataFilePath(tmdbId, language); Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath)); _jsonSerializer.SerializeToFile(seriesInfo, dataFilePath); @@ -147,7 +218,7 @@ namespace MediaBrowser.Providers.TV series.CommunityRating = rating; } - series.Overview = seriesInfo.overview; + series.Overview = seriesInfo.overview; if (seriesInfo.networks != null) { @@ -206,7 +277,7 @@ namespace MediaBrowser.Providers.TV return dataPath; } - + internal async Task DownloadSeriesInfo(string id, string preferredMetadataLanguage, CancellationToken cancellationToken) { var mainResult = await FetchMainResult(id, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false); @@ -241,7 +312,7 @@ namespace MediaBrowser.Providers.TV url += string.Format("&language={0}", language); } - + // Get images in english and with no language url += "&include_image_language=" + string.Join(",", imageLanguages.ToArray()); @@ -258,7 +329,7 @@ namespace MediaBrowser.Providers.TV return _jsonSerializer.DeserializeFromStream<RootObject>(json); } } - + private readonly Task _cachedTask = Task.FromResult(true); internal Task EnsureSeriesInfo(string tmdbId, string language, CancellationToken cancellationToken) { @@ -328,10 +399,10 @@ namespace MediaBrowser.Providers.TV return false; } - private async Task<string> FindIdByExternalId(string id, string externalSource, CancellationToken cancellationToken) + private async Task<RemoteSearchResult> FindByExternalId(string id, string externalSource, CancellationToken cancellationToken) { - var url = string.Format("http://api.themoviedb.org/3/tv/find/{0}?api_key={1}&external_source={2}", - id, + var url = string.Format("http://api.themoviedb.org/3/tv/find/{0}?api_key={1}&external_source={2}", + id, MovieDbProvider.ApiKey, externalSource); @@ -351,7 +422,19 @@ namespace MediaBrowser.Providers.TV if (tv != null) { - return tv.id.ToString(_usCulture); + var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); + var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + + var remoteResult = new RemoteSearchResult + { + Name = tv.name, + SearchProviderName = Name, + ImageUrl = string.IsNullOrWhiteSpace(tv.poster_path) ? null : tmdbImageUrl + tv.poster_path + }; + + remoteResult.SetProviderId(MetadataProviders.Tmdb, tv.id.ToString(_usCulture)); + + return remoteResult; } } } @@ -462,7 +545,12 @@ namespace MediaBrowser.Providers.TV public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) { - throw new NotImplementedException(); + return _httpClient.GetResponse(new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = url, + ResourcePool = MovieDbProvider.Current.MovieDbResourcePool + }); } } } diff --git a/MediaBrowser.Providers/TV/SeriesXmlParser.cs b/MediaBrowser.Providers/TV/SeriesXmlParser.cs index 8ed25bc7e..0c220031c 100644 --- a/MediaBrowser.Providers/TV/SeriesXmlParser.cs +++ b/MediaBrowser.Providers/TV/SeriesXmlParser.cs @@ -74,6 +74,21 @@ namespace MediaBrowser.Providers.TV break; } + case "AnimeSeriesIndex": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + int num; + + if (int.TryParse(number, out num)) + { + item.AnimeSeriesIndex = num; + } + } + break; + } case "SeriesName": item.Name = reader.ReadElementContentAsString(); break; diff --git a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs index e24b72eff..32ed5d7f6 100644 --- a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs +++ b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs @@ -73,6 +73,12 @@ namespace MediaBrowser.Providers.TV /// <returns>Task.</returns> public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) { + if (!_config.Configuration.EnableInternetProviders) + { + progress.Report(100); + return; + } + var seriesConfig = _config.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, typeof(Series).Name, StringComparison.OrdinalIgnoreCase)); if (seriesConfig != null && seriesConfig.DisabledMetadataFetchers.Contains(TvdbSeriesProvider.Current.Name, StringComparer.OrdinalIgnoreCase)) diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index 51eec8668..4bd22107c 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -50,6 +50,12 @@ namespace MediaBrowser.Providers.TV public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) { + var seriesId = searchInfo.GetProviderId(MetadataProviders.Tvdb); + + if (!string.IsNullOrEmpty(seriesId)) + { + } + return new List<RemoteSearchResult>(); } @@ -1092,7 +1098,12 @@ namespace MediaBrowser.Providers.TV public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) { - throw new NotImplementedException(); + return _httpClient.GetResponse(new HttpRequestOptions + { + CancellationToken = cancellationToken, + Url = url, + ResourcePool = TvDbResourcePool + }); } } } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index fee80c317..7bf87875e 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -664,6 +664,7 @@ namespace MediaBrowser.Server.Implementations.Dto } dto.DisplayMediaType = item.DisplayMediaType; + dto.IsUnidentified = item.IsUnidentified; if (fields.Contains(ItemFields.Settings)) { @@ -969,6 +970,12 @@ namespace MediaBrowser.Server.Implementations.Dto } } + var supportsPlaceHolders = item as ISupportsPlaceHolders; + if (supportsPlaceHolders != null) + { + dto.IsPlaceHolder = supportsPlaceHolders.IsPlaceHolder; + } + // Add audio info var audio = item as Audio; if (audio != null) @@ -1092,6 +1099,8 @@ namespace MediaBrowser.Server.Implementations.Dto { dto.DisplaySpecialsWithSeasons = series.DisplaySpecialsWithSeasons; } + + dto.AnimeSeriesIndex = series.AnimeSeriesIndex; } if (episode != null) diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 43037d6ce..c0d784fcc 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints public void Run() { - NatUtility.Logger = new LogWriter(_logger); + //NatUtility.Logger = new LogWriter(_logger); Reload(); } @@ -64,17 +64,17 @@ namespace MediaBrowser.Server.Implementations.EntryPoints void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) { - var ex = e.ExceptionObject as Exception; - - if (ex == null) - { - _logger.Error("Unidentified error reported by Mono.Nat"); - } - else - { - // Seeing some blank exceptions coming through here - _logger.ErrorException("Error reported by Mono.Nat: ", ex); - } + //var ex = e.ExceptionObject as Exception; + + //if (ex == null) + //{ + // _logger.Error("Unidentified error reported by Mono.Nat"); + //} + //else + //{ + // // Seeing some blank exceptions coming through here + // _logger.ErrorException("Error reported by Mono.Nat: ", ex); + //} } void NatUtility_DeviceFound(object sender, DeviceEventArgs e) @@ -88,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints } catch (Exception ex) { - _logger.ErrorException("Error creating port forwarding rules", ex); + //_logger.ErrorException("Error creating port forwarding rules", ex); } } @@ -106,7 +106,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private void CreatePortMap(INatDevice device, int port) { - _logger.Info("Creating port map on port {0}", port); + _logger.Debug("Creating port map on port {0}", port); device.CreatePortMap(new Mapping(Protocol.Tcp, port, port) { diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 66e9e4fa1..6e9d803bf 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -451,7 +451,7 @@ namespace MediaBrowser.Server.Implementations.Library } } - if (options.DeleteFileLocation && (locationType == LocationType.FileSystem || locationType == LocationType.Offline)) + if (options.DeleteFileLocation && locationType != LocationType.Remote && locationType != LocationType.Virtual) { foreach (var path in item.GetDeletePaths().ToList()) { @@ -922,6 +922,9 @@ namespace MediaBrowser.Server.Implementations.Library /// <returns>Task.</returns> public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress) { + // Ensure the location is unavailable. + Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath); + return new PeopleValidator(this, _logger).ValidatePeople(cancellationToken, progress); } @@ -933,6 +936,9 @@ namespace MediaBrowser.Server.Implementations.Library /// <returns>Task.</returns> public Task ValidateArtists(CancellationToken cancellationToken, IProgress<double> progress) { + // Ensure the location is unavailable. + Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.ArtistsPath); + return new ArtistsValidator(this, _userManager, _logger).Run(progress, cancellationToken); } @@ -944,6 +950,9 @@ namespace MediaBrowser.Server.Implementations.Library /// <returns>Task.</returns> public Task ValidateMusicGenres(CancellationToken cancellationToken, IProgress<double> progress) { + // Ensure the location is unavailable. + Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.MusicGenrePath); + return new MusicGenresValidator(this, _userManager, _logger).Run(progress, cancellationToken); } @@ -955,6 +964,9 @@ namespace MediaBrowser.Server.Implementations.Library /// <returns>Task.</returns> public Task ValidateGameGenres(CancellationToken cancellationToken, IProgress<double> progress) { + // Ensure the location is unavailable. + Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.GameGenrePath); + return new GameGenresValidator(this, _userManager, _logger).Run(progress, cancellationToken); } @@ -966,6 +978,9 @@ namespace MediaBrowser.Server.Implementations.Library /// <returns>Task.</returns> public Task ValidateStudios(CancellationToken cancellationToken, IProgress<double> progress) { + // Ensure the location is unavailable. + Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.StudioPath); + return new StudiosValidator(this, _userManager, _logger).Run(progress, cancellationToken); } @@ -977,6 +992,9 @@ namespace MediaBrowser.Server.Implementations.Library /// <returns>Task.</returns> public Task ValidateGenres(CancellationToken cancellationToken, IProgress<double> progress) { + // Ensure the location is unavailable. + Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.GenrePath); + return new GenresValidator(this, _userManager, _logger).Run(progress, cancellationToken); } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index 7e643cd99..871171541 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -132,6 +132,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio return true; } if (EntityResolutionHelper.IsVideoFile(fullName)) return false; + if (EntityResolutionHelper.IsVideoPlaceHolder(fullName)) return false; } // or a single audio file and no video files diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 192f84a6f..bd315530e 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -7,7 +7,6 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Sorting; @@ -49,7 +48,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv private List<Guid> _channelIdList = new List<Guid>(); private Dictionary<Guid, LiveTvProgram> _programs = new Dictionary<Guid, LiveTvProgram>(); - private SemaphoreSlim _refreshSemaphore = new SemaphoreSlim(1, 1); + private readonly SemaphoreSlim _refreshSemaphore = new SemaphoreSlim(1, 1); public LiveTvManager(IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager) { diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs index 6f4b7a8a7..f74865d2c 100644 --- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -84,6 +84,11 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder /// <returns><c>true</c> if [is eligible for chapter image extraction] [the specified video]; otherwise, <c>false</c>.</returns> private bool IsEligibleForChapterImageExtraction(Video video) { + if (video.IsPlaceHolder) + { + return false; + } + if (video is Movie) { if (!_config.Configuration.EnableMovieChapterImageExtraction) diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 73f99cda1..1907344a1 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -336,6 +336,42 @@ namespace MediaBrowser.ServerApplication { // Not there, no big deal } + + try + { + Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "fanart-movies"), true); + } + catch (IOException) + { + // Not there, no big deal + } + + try + { + Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "fanart-music"), true); + } + catch (IOException) + { + // Not there, no big deal + } + + try + { + Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "fanart-tv"), true); + } + catch (IOException) + { + // Not there, no big deal + } + + try + { + Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "tmdb-people"), true); + } + catch (IOException) + { + // Not there, no big deal + } }); } @@ -812,7 +848,8 @@ namespace MediaBrowser.ServerApplication HasUpdateAvailable = _hasUpdateAvailable, SupportsAutoRunAtStartup = SupportsAutoRunAtStartup, TranscodingTempPath = ApplicationPaths.TranscodingTempPath, - IsRunningAsService = IsRunningAsService + IsRunningAsService = IsRunningAsService, + ServerName = string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.ServerName) ? Environment.MachineName : ServerConfigurationManager.Configuration.ServerName }; } diff --git a/MediaBrowser.ServerApplication/LibraryViewer.cs b/MediaBrowser.ServerApplication/LibraryViewer.cs index 2bf51be4a..a8eda801b 100644 --- a/MediaBrowser.ServerApplication/LibraryViewer.cs +++ b/MediaBrowser.ServerApplication/LibraryViewer.cs @@ -84,7 +84,8 @@ namespace MediaBrowser.ServerApplication { treeView1.Nodes.Clear(); - IEnumerable<BaseItem> children = _currentUser.Name == "Physical" ? new[] { _libraryManager.RootFolder } : _libraryManager.RootFolder.GetChildren(_currentUser, true); + var isPhysical = _currentUser.Name == "Physical"; + IEnumerable<BaseItem> children = isPhysical ? new[] { _libraryManager.RootFolder } : _libraryManager.RootFolder.GetChildren(_currentUser, true); children = OrderByName(children, _currentUser); foreach (Folder folder in children) @@ -94,9 +95,9 @@ namespace MediaBrowser.ServerApplication var node = new TreeNode { Tag = currentFolder }; - var subChildren = currentFolder.GetChildren(_currentUser, true); + var subChildren = isPhysical ? currentFolder.Children : currentFolder.GetChildren(_currentUser, true); subChildren = OrderByName(subChildren, _currentUser); - AddChildren(node, subChildren, _currentUser); + AddChildren(node, subChildren, _currentUser, isPhysical); node.Text = currentFolder.Name + " (" + node.Nodes.Count + ")"; @@ -110,7 +111,7 @@ namespace MediaBrowser.ServerApplication /// <param name="parent">The parent.</param> /// <param name="children">The children.</param> /// <param name="user">The user.</param> - private void AddChildren(TreeNode parent, IEnumerable<BaseItem> children, User user) + private void AddChildren(TreeNode parent, IEnumerable<BaseItem> children, User user, bool isPhysical) { foreach (var item in children) { @@ -120,7 +121,9 @@ namespace MediaBrowser.ServerApplication { var prefs = _displayPreferencesManager.GetDisplayPreferences(subFolder.DisplayPreferencesId, user.Id, "LibraryExplorer"); - AddChildren(node, OrderBy(subFolder.GetChildren(user, true), user, prefs.SortBy), user); + var subChildren = isPhysical ? subFolder.Children : subFolder.GetChildren(_currentUser, true); + + AddChildren(node, OrderBy(subChildren, user, prefs.SortBy), user, isPhysical); node.Text = item.Name + " (" + node.Nodes.Count + ")"; } else diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index e5d62a256..0e6010fd0 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -416,7 +416,7 @@ namespace MediaBrowser.WebDashboard.Api var files = new[] { - "thirdparty/jquerymobile-1.4.1/jquery.mobile-1.4.1.min.css", + "thirdparty/jquerymobile-1.4.2/jquery.mobile-1.4.2.min.css", "css/all.css" + versionString }; @@ -497,6 +497,7 @@ namespace MediaBrowser.WebDashboard.Api "itemgallery.js", "itemlistpage.js", "librarypathmapping.js", + "libraryreport.js", "librarysettings.js", "livetvchannel.js", "livetvchannels.js", @@ -570,7 +571,7 @@ namespace MediaBrowser.WebDashboard.Api var newLineBytes = Encoding.UTF8.GetBytes(Environment.NewLine); await AppendResource(memoryStream, "thirdparty/jquery-2.0.3.min.js", newLineBytes).ConfigureAwait(false); - await AppendResource(memoryStream, "thirdparty/jquerymobile-1.4.1/jquery.mobile-1.4.1.min.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/jquerymobile-1.4.2/jquery.mobile-1.4.2.min.js", newLineBytes).ConfigureAwait(false); var versionString = string.Format("window.dashboardVersion='{0}';", _appHost.ApplicationVersion); var versionBytes = Encoding.UTF8.GetBytes(versionString); diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index ea637f109..55f97e1da 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -196,6 +196,9 @@ <Content Include="dashboard-ui\css\images\items\detail\tv.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\images\items\list\remotesearch.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\css\images\media\tvflyout.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -220,6 +223,9 @@ <Content Include="dashboard-ui\librarypathmapping.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\libraryreport.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\livetvchannel.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -487,6 +493,9 @@ <Content Include="dashboard-ui\scripts\librarypathmapping.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\scripts\libraryreport.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\scripts\livetvchannel.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -574,613 +583,613 @@ <Content Include="dashboard-ui\thirdparty\jquery-2.0.3.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\ajax-loader.gif">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\ajax-loader.gif">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\action-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\action-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\action-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\action-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\alert-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\alert-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\alert-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\alert-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-d-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-d-l-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-l-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-d-l-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-l-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-d-r-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-r-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-d-r-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-r-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-d-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-l-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-l-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-l-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-l-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-r-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-r-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-r-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-r-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-u-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-u-l-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-l-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-u-l-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-l-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-u-r-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-r-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-u-r-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-r-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\arrow-u-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\audio-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\audio-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\audio-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\audio-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\back-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\back-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\back-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\back-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\bars-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\bars-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\bars-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\bars-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\bullets-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\bullets-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\bullets-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\bullets-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\calendar-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\calendar-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\calendar-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\calendar-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\camera-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\camera-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\camera-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\camera-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\carat-d-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-d-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\carat-d-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-d-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\carat-l-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-l-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\carat-l-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-l-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\carat-r-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-r-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\carat-r-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-r-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\carat-u-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-u-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\carat-u-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-u-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\check-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\check-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\check-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\check-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\clock-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\clock-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\clock-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\clock-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\cloud-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\cloud-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\cloud-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\cloud-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\comment-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\comment-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\comment-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\comment-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\delete-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\delete-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\delete-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\delete-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\edit-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\edit-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\edit-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\edit-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\eye-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\eye-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\eye-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\eye-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\forbidden-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\forbidden-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\forbidden-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\forbidden-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\forward-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\forward-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\forward-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\forward-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\gear-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\gear-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\gear-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\gear-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\grid-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\grid-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\grid-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\grid-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\heart-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\heart-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\heart-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\heart-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\home-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\home-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\home-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\home-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\info-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\info-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\info-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\info-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\location-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\location-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\location-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\location-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\lock-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\lock-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\lock-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\lock-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\mail-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\mail-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\mail-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\mail-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\minus-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\minus-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\minus-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\minus-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\navigation-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\navigation-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\navigation-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\navigation-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\phone-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\phone-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\phone-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\phone-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\plus-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\plus-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\plus-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\plus-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\power-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\power-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\power-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\power-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\recycle-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\recycle-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\recycle-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\recycle-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\refresh-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\refresh-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\refresh-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\refresh-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\search-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\search-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\search-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\search-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\shop-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\shop-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\shop-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\shop-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\star-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\star-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\star-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\star-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\tag-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\tag-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\tag-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\tag-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\user-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\user-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\user-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\user-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\video-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\video-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-png\video-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\video-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\action-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\action-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\action-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\action-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\alert-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\alert-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\alert-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\alert-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-d-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-d-l-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-l-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-d-l-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-l-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-d-r-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-r-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-d-r-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-r-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-d-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-l-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-l-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-l-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-l-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-r-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-r-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-r-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-r-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-u-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-u-l-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-l-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-u-l-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-l-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-u-r-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-r-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-u-r-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-r-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\arrow-u-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\audio-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\audio-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\audio-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\audio-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\back-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\back-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\back-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\back-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\bars-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\bars-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\bars-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\bars-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\bullets-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\bullets-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\bullets-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\bullets-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\calendar-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\calendar-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\calendar-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\calendar-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\camera-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\camera-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\camera-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\camera-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\carat-d-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-d-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\carat-d-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-d-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\carat-l-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-l-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\carat-l-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-l-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\carat-r-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-r-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\carat-r-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-r-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\carat-u-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-u-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\carat-u-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-u-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\check-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\check-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\check-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\check-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\clock-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\clock-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\clock-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\clock-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\cloud-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\cloud-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\cloud-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\cloud-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\comment-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\comment-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\comment-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\comment-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\delete-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\delete-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\delete-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\delete-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\edit-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\edit-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\edit-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\edit-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\eye-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\eye-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\eye-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\eye-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\forbidden-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\forbidden-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\forbidden-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\forbidden-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\forward-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\forward-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\forward-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\forward-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\gear-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\gear-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\gear-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\gear-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\grid-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\grid-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\grid-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\grid-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\heart-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\heart-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\heart-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\heart-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\home-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\home-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\home-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\home-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\info-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\info-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\info-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\info-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\location-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\location-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\location-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\location-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\lock-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\lock-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\lock-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\lock-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\mail-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\mail-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\mail-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\mail-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\minus-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\minus-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\minus-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\minus-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\navigation-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\navigation-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\navigation-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\navigation-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\phone-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\phone-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\phone-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\phone-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\plus-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\plus-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\plus-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\plus-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\power-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\power-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\power-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\power-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\recycle-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\recycle-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\recycle-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\recycle-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\refresh-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\refresh-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\refresh-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\refresh-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\search-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\search-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\search-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\search-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\shop-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\shop-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\shop-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\shop-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\star-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\star-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\star-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\star-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\tag-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\tag-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\tag-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\tag-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\user-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\user-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\user-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\user-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\video-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\video-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\images\icons-svg\video-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\video-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\jquery.mobile-1.4.1.min.css">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\jquery.mobile-1.4.2.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.1\jquery.mobile-1.4.1.min.js">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\jquery.mobile-1.4.2.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\thirdparty\jstree1.0\jquery.jstree.min.js">
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index db84d93e6..e570f18d8 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common.Internal</id> - <version>3.0.333</version> + <version>3.0.335</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.333" /> + <dependency id="MediaBrowser.Common" version="3.0.335" /> <dependency id="NLog" version="2.1.0" /> <dependency id="SimpleInjector" version="2.4.1" /> <dependency id="sharpcompress" version="0.10.2" /> diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index c87a9c304..75b695584 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.333</version> + <version>3.0.335</version> <title>MediaBrowser.Common</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 573356d22..581a82106 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Server.Core</id> - <version>3.0.333</version> + <version>3.0.335</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.333" /> + <dependency id="MediaBrowser.Common" version="3.0.335" /> </dependencies> </metadata> <files> |
