diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index 9fc4bb3d04..a244b71df5 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -271,6 +271,16 @@ namespace MediaBrowser.Api item.Overview = request.Overview; item.Genres = request.Genres; + var episode = item as Episode; + if (episode != null) + { + episode.DvdSeasonNumber = request.DvdSeasonNumber; + episode.DvdEpisodeNumber = request.DvdEpisodeNumber; + episode.AirsAfterSeasonNumber = request.AirsAfterSeasonNumber; + episode.AirsBeforeEpisodeNumber = request.AirsBeforeEpisodeNumber; + episode.AirsBeforeSeasonNumber = request.AirsBeforeSeasonNumber; + } + var hasTags = item as IHasTags; if (hasTags != null) { diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index b1e0339fcb..f33db49790 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -38,14 +38,6 @@ Always - - False - ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll - - - False - ..\ThirdParty\ServiceStack\ServiceStack.Text.dll - @@ -56,6 +48,12 @@ ..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll + + ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll + + + ..\ThirdParty\ServiceStack\ServiceStack.Text.dll + diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index 7d75cfd3db..0d35cb4da0 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -37,14 +37,6 @@ Always - - False - ..\ThirdParty\ServiceStack\ServiceStack.Text.dll - - - False - ..\packages\sharpcompress.0.10.2\lib\net40\SharpCompress.dll - @@ -58,6 +50,12 @@ ..\packages\SimpleInjector.2.3.6\lib\net40-client\SimpleInjector.dll + + ..\ThirdParty\ServiceStack\ServiceStack.Text.dll + + + ..\packages\sharpcompress.0.10.2\lib\net40\SharpCompress.dll + diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index e7593b075e..1d38b37281 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1359,13 +1359,24 @@ namespace MediaBrowser.Controller.Entities Logger.ErrorException("Error getting ResolveArgs for {0}", ex, Path); } - //this should be functionally equivilent to what was here since it is IEnum and works on a thread-safe copy return RecursiveChildren.Where(i => i.LocationType != LocationType.Virtual).FirstOrDefault(i => { try { - return string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) - || i.ResolveArgs.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase); + if (string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + if (i.LocationType != LocationType.Remote) + { + if (i.ResolveArgs.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; } catch (IOException ex) { diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index e9f250d2a4..f24d86408e 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -40,6 +40,17 @@ namespace MediaBrowser.Controller.Entities.TV public int? AirsAfterSeasonNumber { get; set; } public int? AirsBeforeEpisodeNumber { get; set; } + /// + /// Gets or sets the DVD season number. + /// + /// The DVD season number. + public int? DvdSeasonNumber { get; set; } + /// + /// Gets or sets the DVD episode number. + /// + /// The DVD episode number. + public float? DvdEpisodeNumber { get; set; } + /// /// We want to group into series not show individually in an index /// diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index e296e0f182..c34180eb61 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -130,7 +130,7 @@ namespace MediaBrowser.Controller.Library { get { - return IsDirectory && Path.Equals(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase); + return IsDirectory && string.Equals(Path, _appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase); } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index f1f2aaf5ef..8d03f84807 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -58,10 +58,6 @@ 4 - - False - ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll - @@ -74,6 +70,9 @@ ..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll + + ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll + diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 20f60586c1..3bdbf2ae67 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -30,11 +30,20 @@ namespace MediaBrowser.Model.Dto /// The date created. public DateTime? DateCreated { get; set; } + public int? AirsBeforeSeasonNumber { get; set; } + public int? AirsAfterSeasonNumber { get; set; } + public int? AirsBeforeEpisodeNumber { get; set; } + + /// + /// Gets or sets the DVD season number. + /// + /// The DVD season number. + public int? DvdSeasonNumber { get; set; } /// - /// Gets or sets the special season number. + /// Gets or sets the DVD episode number. /// - /// The special season number. - public int? SpecialSeasonNumber { get; set; } + /// The DVD episode number. + public float? DvdEpisodeNumber { get; set; } /// /// Gets or sets the name of the sort. diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 6a17ad133a..ade4e96fdf 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -110,6 +110,12 @@ namespace MediaBrowser.Model.System /// The HTTP server port number. public int HttpServerPortNumber { get; set; } + /// + /// Gets or sets the wan address. + /// + /// The wan address. + public string WanAddress { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/MediaBrowser.Mono.sln b/MediaBrowser.Mono.sln index 397763489a..bfd30573ec 100644 --- a/MediaBrowser.Mono.sln +++ b/MediaBrowser.Mono.sln @@ -36,8 +36,8 @@ Global {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.Build.0 = Debug|x86 {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.Build.0 = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.ActiveCfg = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.Build.0 = Release|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.ActiveCfg = Release|x86 + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.Build.0 = Release|x86 {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.ActiveCfg = Debug|Any CPU {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.Build.0 = Debug|Any CPU {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -82,6 +82,6 @@ Global {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = MediaBrowser.Model\MediaBrowser.Model.csproj + StartupItem = MediaBrowser.Server.Mono\MediaBrowser.Server.Mono.csproj EndGlobalSection EndGlobal diff --git a/MediaBrowser.Mono.userprefs b/MediaBrowser.Mono.userprefs index 51ba9d804b..d07dfa4cbf 100644 --- a/MediaBrowser.Mono.userprefs +++ b/MediaBrowser.Mono.userprefs @@ -1,13 +1,29 @@  - - + + - + + + + - - + + + + + + + + + + + + + + + @@ -21,6 +37,7 @@ + diff --git a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs index e483b1d61e..952d7e218e 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs @@ -325,6 +325,7 @@ namespace MediaBrowser.Providers.Movies { continue; } + break; } } } diff --git a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs index aff71c6dbb..9bd73bf656 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPrescanTask.cs @@ -16,7 +16,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Movies { - class FanArtMovieUpdatesPrescanTask : ILibraryPrescanTask + class FanArtMovieUpdatesPrescanTask : ILibraryPostScanTask { private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmovies/{0}/{1}/"; diff --git a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs index f8fb133c60..46e947c70c 100644 --- a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs +++ b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs @@ -16,7 +16,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Movies { - public class MovieUpdatesPreScanTask : ILibraryPrescanTask + public class MovieUpdatesPreScanTask : ILibraryPostScanTask { /// /// The updates URL diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs index 161c96a5dd..2e072b0983 100644 --- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs @@ -203,6 +203,7 @@ namespace MediaBrowser.Providers.Music { continue; } + break; } } } diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs index 4830d15b17..57a191ab13 100644 --- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs @@ -328,6 +328,7 @@ namespace MediaBrowser.Providers.Music { continue; } + break; } } } diff --git a/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs b/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs index ddf2121792..a3d0deb0e0 100644 --- a/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs +++ b/MediaBrowser.Providers/Music/FanArtUpdatesPrescanTask.cs @@ -15,7 +15,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Music { - class FanArtUpdatesPrescanTask : ILibraryPrescanTask + class FanArtUpdatesPrescanTask : ILibraryPostScanTask { private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmusic/{0}/{1}/"; diff --git a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs index 35dd551f13..88b3af5be0 100644 --- a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs @@ -92,6 +92,16 @@ namespace MediaBrowser.Providers.Savers builder.Append("" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + ""); } + if (episode.DvdEpisodeNumber.HasValue) + { + builder.Append("" + SecurityElement.Escape(episode.DvdEpisodeNumber.Value.ToString(_usCulture)) + ""); + } + + if (episode.DvdSeasonNumber.HasValue) + { + builder.Append("" + SecurityElement.Escape(episode.DvdSeasonNumber.Value.ToString(_usCulture)) + ""); + } + if (episode.PremiereDate.HasValue) { builder.Append("" + SecurityElement.Escape(episode.PremiereDate.Value.ToString("yyyy-MM-dd")) + ""); @@ -113,7 +123,9 @@ namespace MediaBrowser.Providers.Savers "EpisodeNumberEnd", "airsafter_season", "airsbefore_episode", - "airsbefore_season" + "airsbefore_season", + "DVD_episodenumber", + "DVD_season" }); } diff --git a/MediaBrowser.Providers/TV/EpisodeXmlParser.cs b/MediaBrowser.Providers/TV/EpisodeXmlParser.cs index 5d970107e4..a06a3bf23b 100644 --- a/MediaBrowser.Providers/TV/EpisodeXmlParser.cs +++ b/MediaBrowser.Providers/TV/EpisodeXmlParser.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities.TV; +using System; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Logging; @@ -40,7 +41,7 @@ namespace MediaBrowser.Providers.TV } private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - + /// /// Fetches the data from XML node. /// @@ -142,6 +143,38 @@ namespace MediaBrowser.Providers.TV break; } + case "DVD_episodenumber": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + float num; + + if (float.TryParse(number, NumberStyles.Any, UsCulture, out num)) + { + item.DvdEpisodeNumber = num; + } + } + break; + } + + case "DVD_season": + { + var number = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(number)) + { + float num; + + if (float.TryParse(number, NumberStyles.Any, UsCulture, out num)) + { + item.DvdSeasonNumber = Convert.ToInt32(num); + } + } + break; + } + case "airsbefore_episode": { var val = reader.ReadElementContentAsString(); diff --git a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs index ed5145bc25..713a95b26c 100644 --- a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs @@ -143,6 +143,7 @@ namespace MediaBrowser.Providers.TV { continue; } + break; } } } diff --git a/MediaBrowser.Providers/TV/FanArtTVProvider.cs b/MediaBrowser.Providers/TV/FanArtTVProvider.cs index 251420261c..90af81ec37 100644 --- a/MediaBrowser.Providers/TV/FanArtTVProvider.cs +++ b/MediaBrowser.Providers/TV/FanArtTVProvider.cs @@ -264,6 +264,7 @@ namespace MediaBrowser.Providers.TV { continue; } + break; } } } diff --git a/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs b/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs index 8ef04ed118..46137a2110 100644 --- a/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs +++ b/MediaBrowser.Providers/TV/FanArtTvUpdatesPrescanTask.cs @@ -16,7 +16,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.TV { - class FanArtTvUpdatesPrescanTask : ILibraryPrescanTask + class FanArtTvUpdatesPrescanTask : ILibraryPostScanTask { private const string UpdatesUrl = "http://api.fanart.tv/webservice/newtv/{0}/{1}/"; diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs index 5d9f387fea..b7709b5d35 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs @@ -404,6 +404,40 @@ namespace MediaBrowser.Providers.TV break; } + case "DVD_episodenumber": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + float num; + + if (float.TryParse(val, NumberStyles.Any, _usCulture, out num)) + { + item.DvdEpisodeNumber = num; + } + } + + break; + } + + case "DVD_season": + { + var val = reader.ReadElementContentAsString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + float num; + + if (float.TryParse(val, NumberStyles.Any, _usCulture, out num)) + { + item.DvdSeasonNumber = Convert.ToInt32(num); + } + } + + break; + } + case "airsbefore_episode": { var val = reader.ReadElementContentAsString(); diff --git a/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs index cdfe86dac7..c5e5327c33 100644 --- a/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.IO; +using System.Net; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -6,6 +7,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; using MediaBrowser.Model.Providers; using System; using System.Collections.Generic; @@ -159,24 +161,12 @@ namespace MediaBrowser.Providers.TV { if (!item.HasImage(ImageType.Primary)) { - var image = images.FirstOrDefault(i => i.Type == ImageType.Primary); - - if (image != null) - { - await _providerManager.SaveImage(item, image.Url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Primary, null, cancellationToken) - .ConfigureAwait(false); - } + await SaveImage(item, images, ImageType.Primary, cancellationToken).ConfigureAwait(false); } if (ConfigurationManager.Configuration.DownloadSeasonImages.Banner && !item.HasImage(ImageType.Banner)) { - var image = images.FirstOrDefault(i => i.Type == ImageType.Banner); - - if (image != null) - { - await _providerManager.SaveImage(item, image.Url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Banner, null, cancellationToken) - .ConfigureAwait(false); - } + await SaveImage(item, images, ImageType.Banner, cancellationToken).ConfigureAwait(false); } if (ConfigurationManager.Configuration.DownloadSeasonImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit) @@ -196,5 +186,26 @@ namespace MediaBrowser.Providers.TV } } } + + private async Task SaveImage(BaseItem item, List images, ImageType type, CancellationToken cancellationToken) + { + foreach (var image in images.Where(i => i.Type == type)) + { + try + { + await _providerManager.SaveImage(item, image.Url, TvdbSeriesProvider.Current.TvDbResourcePool, type, null, cancellationToken).ConfigureAwait(false); + break; + } + catch (HttpException ex) + { + // Sometimes fanart has bad url's in their xml + if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound) + { + continue; + } + break; + } + } + } } } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index ba9dd170df..6e8c9d3ebe 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1061,7 +1061,12 @@ namespace MediaBrowser.Server.Implementations.Dto if (episode != null) { dto.IndexNumberEnd = episode.IndexNumberEnd; - dto.SpecialSeasonNumber = episode.AirsAfterSeasonNumber ?? episode.AirsBeforeSeasonNumber; + + dto.DvdSeasonNumber = episode.DvdSeasonNumber; + dto.DvdEpisodeNumber = episode.DvdEpisodeNumber; + dto.AirsAfterSeasonNumber = episode.AirsAfterSeasonNumber; + dto.AirsBeforeEpisodeNumber = episode.AirsBeforeEpisodeNumber; + dto.AirsBeforeSeasonNumber = episode.AirsBeforeSeasonNumber; var seasonId = episode.SeasonId; if (seasonId.HasValue) diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 29dce67476..5e4c6f0aaf 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -63,8 +63,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer _logger = logManager.GetLogger("HttpServer"); - LogManager.LogFactory = new ServerLogFactory(logManager); - _containerAdapter = new ContainerAdapter(applicationHost); for (var i = 0; i < 2; i++) @@ -477,7 +475,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer ServiceController = CreateServiceController(); _logger.Info("Calling ServiceStack AppHost.Init"); - Init(); + + base.Init(); } /// diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs index 57acddc432..c403c09b44 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/ServerFactory.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Logging; +using ServiceStack.Logging; namespace MediaBrowser.Server.Implementations.HttpServer { @@ -20,6 +21,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer /// IHttpServer. public static IHttpServer CreateServer(IApplicationHost applicationHost, ILogManager logManager, string serverName, string handlerPath, string defaultRedirectpath) { + LogManager.LogFactory = new ServerLogFactory(logManager); + return new HttpListenerHost(applicationHost, logManager, serverName, handlerPath, defaultRedirectpath); } } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 03e29dd38f..e335f4ad5d 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -116,6 +116,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies return null; } + var filename = Path.GetFileName(args.Path); + // Don't misidentify xbmc trailers as a movie + if (filename.IndexOf(BaseItem.XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) != -1) + { + return null; + } + // Find movies that are mixed in the same folder if (args.Path.IndexOf("[trailers]", StringComparison.OrdinalIgnoreCase) != -1 || string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.Server.Implementations/Localization/Ratings/de.txt b/MediaBrowser.Server.Implementations/Localization/Ratings/de.txt index 571b6eba95..e1c3639cb4 100644 --- a/MediaBrowser.Server.Implementations/Localization/Ratings/de.txt +++ b/MediaBrowser.Server.Implementations/Localization/Ratings/de.txt @@ -2,4 +2,5 @@ DE-FSK0,1 DE-FSK6+,5 DE-FSK12+,7 DE-FSK16+,8 +DE-16,8 DE-FSK18+,9 diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 39966f0d7a..70b173fd9f 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -37,25 +37,8 @@ ..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll - - False - ..\ThirdParty\ServiceStack\ServiceStack.dll - - - False - ..\ThirdParty\ServiceStack\ServiceStack.Client.dll - - - False - ..\ThirdParty\ServiceStack\ServiceStack.Common.dll - - - False - ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll - - - False - ..\ThirdParty\ServiceStack\ServiceStack.Text.dll + + ..\ThirdParty\Mono.Data.Sqlite\Mono.Data.Sqlite.dll @@ -73,6 +56,21 @@ ..\packages\System.Data.SQLite.x86.1.0.89.0\lib\net45\System.Data.SQLite.dll + + ..\ThirdParty\ServiceStack\ServiceStack.dll + + + ..\ThirdParty\ServiceStack\ServiceStack.Client.dll + + + ..\ThirdParty\ServiceStack\ServiceStack.Common.dll + + + ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll + + + ..\ThirdParty\ServiceStack\ServiceStack.Text.dll + @@ -169,6 +167,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteChapterRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteChapterRepository.cs index 075ef42398..5842b05a34 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteChapterRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteChapterRepository.cs @@ -32,6 +32,8 @@ namespace MediaBrowser.Server.Implementations.Persistence _logger = logManager.GetLogger(GetType().Name); } + private SqliteShrinkMemoryTimer _shrinkMemoryTimer; + /// /// Opens the connection to the database /// @@ -52,6 +54,8 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.RunQueries(queries, _logger); PrepareStatements(); + + _shrinkMemoryTimer = new SqliteShrinkMemoryTimer(_connection, _writeLock, _logger); } /// @@ -282,6 +286,12 @@ namespace MediaBrowser.Server.Implementations.Persistence { lock (_disposeLock) { + if (_shrinkMemoryTimer != null) + { + _shrinkMemoryTimer.Dispose(); + _shrinkMemoryTimer = null; + } + if (_connection != null) { if (_connection.IsOpen()) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs index 5d836b090d..9971c74605 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs @@ -25,6 +25,8 @@ namespace MediaBrowser.Server.Implementations.Persistence _logger = logManager.GetLogger(GetType().Name); } + private SqliteShrinkMemoryTimer _shrinkMemoryTimer; + /// /// Opens the connection to the database /// @@ -50,6 +52,8 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.RunQueries(queries, _logger); PrepareStatements(); + + _shrinkMemoryTimer = new SqliteShrinkMemoryTimer(_connection, _writeLock, _logger); } private static readonly string[] SaveColumns = @@ -240,6 +244,12 @@ namespace MediaBrowser.Server.Implementations.Persistence { lock (_disposeLock) { + if (_shrinkMemoryTimer != null) + { + _shrinkMemoryTimer.Dispose(); + _shrinkMemoryTimer = null; + } + if (_connection != null) { if (_connection.IsOpen()) diff --git a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 76971342a0..d6b78bd84b 100644 --- a/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -62,7 +62,7 @@ namespace MediaBrowser.Server.Implementations.Sorting return CompareEpisodes(x, y); } - if (!isXSpecial && isYSpecial) + if (!isXSpecial) { return CompareEpisodeToSpecial(x, y); } @@ -87,8 +87,17 @@ namespace MediaBrowser.Server.Implementations.Sorting // Add 1 to to non-specials to account for AirsBeforeEpisodeNumber var xEpisode = x.IndexNumber ?? -1; xEpisode++; + var yEpisode = y.AirsBeforeEpisodeNumber ?? 10000; + // Sometimes they'll both have a value. + // For example AirsAfterSeasonNumber=1, AirsBeforeSeasonNumber=2, AirsBeforeEpisodeNumber=1 + // The episode should be displayed at the end of season 1 + if (y.AirsAfterSeasonNumber.HasValue && y.AirsBeforeSeasonNumber.HasValue && y.AirsBeforeSeasonNumber.Value > y.AirsAfterSeasonNumber.Value) + { + yEpisode = 10000; + } + return xEpisode.CompareTo(yEpisode); } diff --git a/MediaBrowser.Server.Implementations/Sorting/AlphanumComparator.cs b/MediaBrowser.Server.Implementations/Sorting/AlphanumComparator.cs new file mode 100644 index 0000000000..3fbb01f779 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Sorting/AlphanumComparator.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MediaBrowser.Server.Implementations.Sorting +{ + public class AlphanumComparator : IComparer + { + private enum ChunkType { Alphanumeric, Numeric }; + + private static bool InChunk(char ch, char otherCh) + { + var type = ChunkType.Alphanumeric; + + if (char.IsDigit(otherCh)) + { + type = ChunkType.Numeric; + } + + if ((type == ChunkType.Alphanumeric && char.IsDigit(ch)) + || (type == ChunkType.Numeric && !char.IsDigit(ch))) + { + return false; + } + + return true; + } + + public static int CompareValues(string s1, string s2) + { + if (s1 == null || s2 == null) + { + return 0; + } + + int thisMarker = 0, thisNumericChunk = 0; + int thatMarker = 0, thatNumericChunk = 0; + + while ((thisMarker < s1.Length) || (thatMarker < s2.Length)) + { + if (thisMarker >= s1.Length) + { + return -1; + } + else if (thatMarker >= s2.Length) + { + return 1; + } + char thisCh = s1[thisMarker]; + char thatCh = s2[thatMarker]; + + StringBuilder thisChunk = new StringBuilder(); + StringBuilder thatChunk = new StringBuilder(); + + while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || InChunk(thisCh, thisChunk[0]))) + { + thisChunk.Append(thisCh); + thisMarker++; + + if (thisMarker < s1.Length) + { + thisCh = s1[thisMarker]; + } + } + + while ((thatMarker < s2.Length) && (thatChunk.Length == 0 || InChunk(thatCh, thatChunk[0]))) + { + thatChunk.Append(thatCh); + thatMarker++; + + if (thatMarker < s2.Length) + { + thatCh = s2[thatMarker]; + } + } + + int result = 0; + // If both chunks contain numeric characters, sort them numerically + if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0])) + { + thisNumericChunk = Convert.ToInt32(thisChunk.ToString()); + thatNumericChunk = Convert.ToInt32(thatChunk.ToString()); + + if (thisNumericChunk < thatNumericChunk) + { + result = -1; + } + + if (thisNumericChunk > thatNumericChunk) + { + result = 1; + } + } + else + { + result = thisChunk.ToString().CompareTo(thatChunk.ToString()); + } + + if (result != 0) + { + return result; + } + } + + return 0; + } + + public int Compare(string x, string y) + { + return CompareValues(x, y); + } + } +} diff --git a/MediaBrowser.Server.Implementations/Sorting/NameComparer.cs b/MediaBrowser.Server.Implementations/Sorting/NameComparer.cs index 49f86c485a..83b1b2d16f 100644 --- a/MediaBrowser.Server.Implementations/Sorting/NameComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/NameComparer.cs @@ -1,7 +1,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; -using System; namespace MediaBrowser.Server.Implementations.Sorting { @@ -18,7 +17,7 @@ namespace MediaBrowser.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem x, BaseItem y) { - return string.Compare(x.Name, y.Name, StringComparison.CurrentCultureIgnoreCase); + return AlphanumComparator.CompareValues(x.Name, y.Name); } /// diff --git a/MediaBrowser.Server.Implementations/Sorting/SeriesSortNameComparer.cs b/MediaBrowser.Server.Implementations/Sorting/SeriesSortNameComparer.cs index 4efc3218b2..09612a49c9 100644 --- a/MediaBrowser.Server.Implementations/Sorting/SeriesSortNameComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/SeriesSortNameComparer.cs @@ -16,7 +16,7 @@ namespace MediaBrowser.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem x, BaseItem y) { - return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); + return AlphanumComparator.CompareValues(GetValue(x), GetValue(y)); } private string GetValue(BaseItem item) diff --git a/MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs b/MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs index 873753a2b2..e635cfbe52 100644 --- a/MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/SortNameComparer.cs @@ -1,7 +1,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; -using System; namespace MediaBrowser.Server.Implementations.Sorting { @@ -18,7 +17,7 @@ namespace MediaBrowser.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem x, BaseItem y) { - return string.Compare(x.SortName, y.SortName, StringComparison.CurrentCultureIgnoreCase); + return AlphanumComparator.CompareValues(x.SortName, y.SortName); } /// diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index be7fb7b278..8d59a9a141 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -39,11 +39,8 @@ - - ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Common.dll - - ..\packages\ServiceStack.Common.3.9.70\lib\net35\ServiceStack.Interfaces.dll + ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll @@ -74,6 +71,9 @@ + + EntryPoints\WanAddressEntryPoint.cs + diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 6058c59581..46a7430b02 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -28,7 +28,6 @@ using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; -using MediaBrowser.Model.Serialization; using MediaBrowser.Model.System; using MediaBrowser.Model.Updates; using MediaBrowser.Providers; @@ -49,6 +48,7 @@ using MediaBrowser.Server.Implementations.Providers; using MediaBrowser.Server.Implementations.ServerManager; using MediaBrowser.Server.Implementations.Session; using MediaBrowser.Server.Implementations.WebSocket; +using MediaBrowser.ServerApplication.EntryPoints; using MediaBrowser.ServerApplication.FFMpeg; using MediaBrowser.ServerApplication.IO; using MediaBrowser.ServerApplication.Native; @@ -616,7 +616,8 @@ namespace MediaBrowser.ServerApplication HttpServerPortNumber = ServerConfigurationManager.Configuration.HttpServerPortNumber, OperatingSystem = Environment.OSVersion.ToString(), CanSelfRestart = CanSelfRestart, - CanSelfUpdate = CanSelfUpdate + CanSelfUpdate = CanSelfUpdate, + WanAddress = WanAddressEntryPoint.WanAddress }; } diff --git a/MediaBrowser.ServerApplication/EntryPoints/WanAddressEntryPoint.cs b/MediaBrowser.ServerApplication/EntryPoints/WanAddressEntryPoint.cs new file mode 100644 index 0000000000..44819b3903 --- /dev/null +++ b/MediaBrowser.ServerApplication/EntryPoints/WanAddressEntryPoint.cs @@ -0,0 +1,56 @@ +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Plugins; +using System; +using System.IO; +using System.Threading; + +namespace MediaBrowser.ServerApplication.EntryPoints +{ + public class WanAddressEntryPoint : IServerEntryPoint + { + public static string WanAddress; + private Timer _timer; + private readonly IHttpClient _httpClient; + + public WanAddressEntryPoint(IHttpClient httpClient) + { + _httpClient = httpClient; + } + + public void Run() + { + _timer = new Timer(TimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromHours(24)); + } + + private async void TimerCallback(object state) + { + try + { + using (var stream = await _httpClient.Get(new HttpRequestOptions + { + Url = "http://bot.whatismyipaddress.com/" + + }).ConfigureAwait(false)) + { + using (var reader = new StreamReader(stream)) + { + WanAddress = await reader.ReadToEndAsync().ConfigureAwait(false); + } + } + } + catch (Exception ex) + { + var b = true; + } + } + + public void Dispose() + { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } + } + } +} diff --git a/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs b/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs index a3d4706893..c133e09571 100644 --- a/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs +++ b/MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs @@ -88,7 +88,7 @@ namespace MediaBrowser.ServerApplication Cursor = Cursors.Wait; await Task.Run(() => { - IEnumerable children = CurrentUser.Name == "Physical" ? _libraryManager.RootFolder.Children : _libraryManager.RootFolder.GetChildren(CurrentUser, true); + IEnumerable children = CurrentUser.Name == "Physical" ? new[] { _libraryManager.RootFolder } : _libraryManager.RootFolder.GetChildren(CurrentUser, true); children = OrderByName(children, CurrentUser); foreach (Folder folder in children) @@ -237,9 +237,9 @@ namespace MediaBrowser.ServerApplication { previews.Add(new PreviewItem(item.GetImage(ImageType.Thumb), "Thumb")); } - previews.AddRange( - item.BackdropImagePaths.Select( - image => new PreviewItem(image, "Backdrop"))); + previews.AddRange( + item.BackdropImagePaths.Select( + image => new PreviewItem(image, "Backdrop"))); }); lstPreviews.ItemsSource = previews; lstPreviews.Items.Refresh(); diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index e02bb1d69a..38e082f12e 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -162,6 +162,7 @@ + diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 35ed3f1e26..9d2b42c85d 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -37,16 +37,15 @@ Always - - False - ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll - + + ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll +