aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Providers')
-rw-r--r--MediaBrowser.Providers/Books/AudioBookMetadataService.cs41
-rw-r--r--MediaBrowser.Providers/Books/AudioPodcastMetadataService.cs41
-rw-r--r--MediaBrowser.Providers/Books/BookMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs3
-rw-r--r--MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs9
-rw-r--r--MediaBrowser.Providers/Channels/ChannelMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Folders/FolderMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Folders/UserViewMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/GameGenres/GameGenreImageProvider.cs144
-rw-r--r--MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Games/GameMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Games/GameSystemMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Genres/GenreImageProvider.cs143
-rw-r--r--MediaBrowser.Providers/Genres/GenreMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/ImagesByName/ImageUtils.cs27
-rw-r--r--MediaBrowser.Providers/LiveTv/AudioRecordingService.cs4
-rw-r--r--MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/LiveTv/VideoRecordingService.cs4
-rw-r--r--MediaBrowser.Providers/Manager/ImageSaver.cs30
-rw-r--r--MediaBrowser.Providers/Manager/ItemImageProvider.cs20
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs57
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs78
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj64
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.nuget.targets6
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs55
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs6
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs28
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs2
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs21
-rw-r--r--MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs1
-rw-r--r--MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs14
-rw-r--r--MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs18
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbImageProvider.cs10
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbProvider.cs10
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs3
-rw-r--r--MediaBrowser.Providers/Movies/MovieMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Music/AlbumMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Music/ArtistMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Music/AudioDbAlbumImageProvider.cs3
-rw-r--r--MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs7
-rw-r--r--MediaBrowser.Providers/Music/AudioDbArtistImageProvider.cs3
-rw-r--r--MediaBrowser.Providers/Music/AudioDbArtistProvider.cs9
-rw-r--r--MediaBrowser.Providers/Music/AudioMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Music/FanArtAlbumProvider.cs9
-rw-r--r--MediaBrowser.Providers/Music/FanArtArtistProvider.cs14
-rw-r--r--MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs390
-rw-r--r--MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs220
-rw-r--r--MediaBrowser.Providers/Music/MusicVideoMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbImageProvider.cs8
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbItemProvider.cs10
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbProvider.cs92
-rw-r--r--MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs3
-rw-r--r--MediaBrowser.Providers/People/MovieDbPersonProvider.cs11
-rw-r--r--MediaBrowser.Providers/People/PersonMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/People/TvdbPersonImageProvider.cs97
-rw-r--r--MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Photos/PhotoHelper.cs98
-rw-r--r--MediaBrowser.Providers/Photos/PhotoMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Photos/PhotoProvider.cs169
-rw-r--r--MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Studios/StudioMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Studios/StudiosImageProvider.cs6
-rw-r--r--MediaBrowser.Providers/Subtitles/ConfigurationExtension.cs29
-rw-r--r--MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs340
-rw-r--r--MediaBrowser.Providers/Subtitles/SubtitleManager.cs6
-rw-r--r--MediaBrowser.Providers/TV/DummySeasonProvider.cs6
-rw-r--r--MediaBrowser.Providers/TV/EpisodeMetadataService.cs60
-rw-r--r--MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs9
-rw-r--r--MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs14
-rw-r--r--MediaBrowser.Providers/TV/MissingEpisodeProvider.cs155
-rw-r--r--MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs6
-rw-r--r--MediaBrowser.Providers/TV/SeasonMetadataService.cs25
-rw-r--r--MediaBrowser.Providers/TV/SeriesMetadataService.cs6
-rw-r--r--MediaBrowser.Providers/TV/SeriesPostScanTask.cs232
-rw-r--r--MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs6
-rw-r--r--MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs24
-rw-r--r--MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs6
-rw-r--r--MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs9
-rw-r--r--MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs10
-rw-r--r--MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs9
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs132
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs1219
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs49
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs86
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs84
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs613
-rw-r--r--MediaBrowser.Providers/Users/UserMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Videos/VideoMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/Years/YearMetadataService.cs4
-rw-r--r--MediaBrowser.Providers/packages.config8
-rw-r--r--MediaBrowser.Providers/project.json17
95 files changed, 2430 insertions, 2822 deletions
diff --git a/MediaBrowser.Providers/Books/AudioBookMetadataService.cs b/MediaBrowser.Providers/Books/AudioBookMetadataService.cs
new file mode 100644
index 000000000..696619a8c
--- /dev/null
+++ b/MediaBrowser.Providers/Books/AudioBookMetadataService.cs
@@ -0,0 +1,41 @@
+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.Linq;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+
+namespace MediaBrowser.Providers.Books
+{
+ public class AudioBookMetadataService : MetadataService<AudioBook, SongInfo>
+ {
+ protected override void MergeData(MetadataResult<AudioBook> source, MetadataResult<AudioBook> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
+ {
+ ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+
+ var sourceItem = source.Item;
+ var targetItem = target.Item;
+
+ if (replaceData || targetItem.Artists.Count == 0)
+ {
+ targetItem.Artists = sourceItem.Artists.ToList();
+ }
+
+ if (replaceData || string.IsNullOrEmpty(targetItem.Album))
+ {
+ targetItem.Album = sourceItem.Album;
+ }
+ }
+
+ public AudioBookMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
+ {
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Books/AudioPodcastMetadataService.cs b/MediaBrowser.Providers/Books/AudioPodcastMetadataService.cs
new file mode 100644
index 000000000..86b2cf1b1
--- /dev/null
+++ b/MediaBrowser.Providers/Books/AudioPodcastMetadataService.cs
@@ -0,0 +1,41 @@
+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.Linq;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+
+namespace MediaBrowser.Providers.Books
+{
+ public class AudioPodcastMetadataService : MetadataService<AudioPodcast, SongInfo>
+ {
+ protected override void MergeData(MetadataResult<AudioPodcast> source, MetadataResult<AudioPodcast> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
+ {
+ ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+
+ var sourceItem = source.Item;
+ var targetItem = target.Item;
+
+ if (replaceData || targetItem.Artists.Count == 0)
+ {
+ targetItem.Artists = sourceItem.Artists.ToList();
+ }
+
+ if (replaceData || string.IsNullOrEmpty(targetItem.Album))
+ {
+ targetItem.Album = sourceItem.Album;
+ }
+ }
+
+ public AudioPodcastMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager)
+ {
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Books/BookMetadataService.cs b/MediaBrowser.Providers/Books/BookMetadataService.cs
index 6f4a744c2..ccc69eb62 100644
--- a/MediaBrowser.Providers/Books/BookMetadataService.cs
+++ b/MediaBrowser.Providers/Books/BookMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Books
{
diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
index 2dacb16ca..a625b93b8 100644
--- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
+++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
@@ -9,7 +9,9 @@ using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.BoxSets
{
diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs
index 2dce13ebc..852feab37 100644
--- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs
+++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs
@@ -162,8 +162,7 @@ namespace MediaBrowser.Providers.BoxSets
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
index ab05c959e..547420092 100644
--- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
+++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
@@ -3,7 +3,6 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -17,7 +16,10 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.BoxSets
{
@@ -317,8 +319,7 @@ namespace MediaBrowser.Providers.BoxSets
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/Channels/ChannelMetadataService.cs b/MediaBrowser.Providers/Channels/ChannelMetadataService.cs
index 22e196d72..c2a6c07f9 100644
--- a/MediaBrowser.Providers/Channels/ChannelMetadataService.cs
+++ b/MediaBrowser.Providers/Channels/ChannelMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Channels
{
diff --git a/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs b/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs
index 2f534c12e..c6013a94d 100644
--- a/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs
+++ b/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs
@@ -1,8 +1,10 @@
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
diff --git a/MediaBrowser.Providers/Folders/FolderMetadataService.cs b/MediaBrowser.Providers/Folders/FolderMetadataService.cs
index 8c4737fc4..94125b29d 100644
--- a/MediaBrowser.Providers/Folders/FolderMetadataService.cs
+++ b/MediaBrowser.Providers/Folders/FolderMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Folders
{
diff --git a/MediaBrowser.Providers/Folders/UserViewMetadataService.cs b/MediaBrowser.Providers/Folders/UserViewMetadataService.cs
index b8f58307a..b1410bfd9 100644
--- a/MediaBrowser.Providers/Folders/UserViewMetadataService.cs
+++ b/MediaBrowser.Providers/Folders/UserViewMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Folders
{
diff --git a/MediaBrowser.Providers/GameGenres/GameGenreImageProvider.cs b/MediaBrowser.Providers/GameGenres/GameGenreImageProvider.cs
deleted file mode 100644
index b26f23715..000000000
--- a/MediaBrowser.Providers/GameGenres/GameGenreImageProvider.cs
+++ /dev/null
@@ -1,144 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Providers.Genres;
-using MediaBrowser.Providers.ImagesByName;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using CommonIO;
-
-namespace MediaBrowser.Providers.GameGenres
-{
- public class GameGenreImageProvider : IRemoteImageProvider
- {
- private readonly IServerConfigurationManager _config;
- private readonly IHttpClient _httpClient;
- private readonly IFileSystem _fileSystem;
-
- private readonly SemaphoreSlim _listResourcePool = new SemaphoreSlim(1, 1);
-
- public GameGenreImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
- {
- _config = config;
- _httpClient = httpClient;
- _fileSystem = fileSystem;
- }
-
- public string Name
- {
- get { return ProviderName; }
- }
-
- public static string ProviderName
- {
- get { return "Emby Designs"; }
- }
-
- public bool Supports(IHasImages item)
- {
- return item is GameGenre;
- }
-
- public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
- {
- return new List<ImageType>
- {
- ImageType.Primary,
- ImageType.Thumb
- };
- }
-
- public Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
- {
- return GetImages(item, true, true, cancellationToken);
- }
-
- private async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, bool posters, bool thumbs, CancellationToken cancellationToken)
- {
- var list = new List<RemoteImageInfo>();
-
- if (posters)
- {
- var posterPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotegamegenreposters.txt");
-
- await EnsurePosterList(posterPath, cancellationToken).ConfigureAwait(false);
-
- list.Add(GetImage(item, posterPath, ImageType.Primary, "folder"));
- }
-
- cancellationToken.ThrowIfCancellationRequested();
-
- if (thumbs)
- {
- var thumbsPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotegamegenrethumbs.txt");
-
- await EnsureThumbsList(thumbsPath, cancellationToken).ConfigureAwait(false);
-
- list.Add(GetImage(item, thumbsPath, ImageType.Thumb, "thumb"));
- }
-
- return list.Where(i => i != null);
- }
-
- private RemoteImageInfo GetImage(IHasImages item, string filename, ImageType type, string remoteFilename)
- {
- var list = ImageUtils.GetAvailableImages(filename);
-
- var match = ImageUtils.FindMatch(item, list);
-
- if (!string.IsNullOrEmpty(match))
- {
- var url = GetUrl(match, remoteFilename);
-
- return new RemoteImageInfo
- {
- ProviderName = Name,
- Type = type,
- Url = url
- };
- }
-
- return null;
- }
-
- private string GetUrl(string image, string filename)
- {
- return string.Format("https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/gamegenres/{0}/{1}.jpg", image, filename);
- }
-
- private Task EnsureThumbsList(string file, CancellationToken cancellationToken)
- {
- const string url = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/gamegenrethumbs.txt";
-
- return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, _listResourcePool, cancellationToken);
- }
-
- private Task EnsurePosterList(string file, CancellationToken cancellationToken)
- {
- const string url = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/gamegenreposters.txt";
-
- return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, _listResourcePool, cancellationToken);
- }
-
- public int Order
- {
- get { return 0; }
- }
-
- public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
- {
- return _httpClient.GetResponse(new HttpRequestOptions
- {
- CancellationToken = cancellationToken,
- Url = url,
- BufferContent = false
- });
- }
- }
-}
diff --git a/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs b/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs
index fb2244e32..180d36378 100644
--- a/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs
+++ b/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.GameGenres
{
diff --git a/MediaBrowser.Providers/Games/GameMetadataService.cs b/MediaBrowser.Providers/Games/GameMetadataService.cs
index a44f1d95f..d6f61fa94 100644
--- a/MediaBrowser.Providers/Games/GameMetadataService.cs
+++ b/MediaBrowser.Providers/Games/GameMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Games
{
diff --git a/MediaBrowser.Providers/Games/GameSystemMetadataService.cs b/MediaBrowser.Providers/Games/GameSystemMetadataService.cs
index 6cf2a45a4..5794e8c9b 100644
--- a/MediaBrowser.Providers/Games/GameSystemMetadataService.cs
+++ b/MediaBrowser.Providers/Games/GameSystemMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Games
{
diff --git a/MediaBrowser.Providers/Genres/GenreImageProvider.cs b/MediaBrowser.Providers/Genres/GenreImageProvider.cs
deleted file mode 100644
index 954cd008e..000000000
--- a/MediaBrowser.Providers/Genres/GenreImageProvider.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Providers.ImagesByName;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using CommonIO;
-
-namespace MediaBrowser.Providers.Genres
-{
- public class GenreImageProvider : IRemoteImageProvider
- {
- private readonly IServerConfigurationManager _config;
- private readonly IHttpClient _httpClient;
- private readonly IFileSystem _fileSystem;
-
- private readonly SemaphoreSlim _listResourcePool = new SemaphoreSlim(1, 1);
-
- public GenreImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
- {
- _config = config;
- _httpClient = httpClient;
- _fileSystem = fileSystem;
- }
-
- public string Name
- {
- get { return ProviderName; }
- }
-
- public static string ProviderName
- {
- get { return "Emby Designs"; }
- }
-
- public bool Supports(IHasImages item)
- {
- return item is Genre;
- }
-
- public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
- {
- return new List<ImageType>
- {
- ImageType.Primary,
- ImageType.Thumb
- };
- }
-
- public Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
- {
- return GetImages(item, true, true, cancellationToken);
- }
-
- private async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, bool posters, bool thumbs, CancellationToken cancellationToken)
- {
- var list = new List<RemoteImageInfo>();
-
- if (posters)
- {
- var posterPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotegenreposters.txt");
-
- await EnsurePosterList(posterPath, cancellationToken).ConfigureAwait(false);
-
- list.Add(GetImage(item, posterPath, ImageType.Primary, "folder"));
- }
-
- cancellationToken.ThrowIfCancellationRequested();
-
- if (thumbs)
- {
- var thumbsPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotegenrethumbs.txt");
-
- await EnsureThumbsList(thumbsPath, cancellationToken).ConfigureAwait(false);
-
- list.Add(GetImage(item, thumbsPath, ImageType.Thumb, "thumb"));
- }
-
- return list.Where(i => i != null);
- }
-
- private RemoteImageInfo GetImage(IHasImages item, string filename, ImageType type, string remoteFilename)
- {
- var list = ImageUtils.GetAvailableImages(filename);
-
- var match = ImageUtils.FindMatch(item, list);
-
- if (!string.IsNullOrEmpty(match))
- {
- var url = GetUrl(match, remoteFilename);
-
- return new RemoteImageInfo
- {
- ProviderName = Name,
- Type = type,
- Url = url
- };
- }
-
- return null;
- }
-
- private string GetUrl(string image, string filename)
- {
- return string.Format("https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/genres/{0}/{1}.jpg", image, filename);
- }
-
- private Task EnsureThumbsList(string file, CancellationToken cancellationToken)
- {
- const string url = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/genrethumbs.txt";
-
- return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, _listResourcePool, cancellationToken);
- }
-
- private Task EnsurePosterList(string file, CancellationToken cancellationToken)
- {
- const string url = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/genreposters.txt";
-
- return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, _listResourcePool, cancellationToken);
- }
-
- public int Order
- {
- get { return 0; }
- }
-
- public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
- {
- return _httpClient.GetResponse(new HttpRequestOptions
- {
- CancellationToken = cancellationToken,
- Url = url,
- BufferContent = false
- });
- }
- }
-}
diff --git a/MediaBrowser.Providers/Genres/GenreMetadataService.cs b/MediaBrowser.Providers/Genres/GenreMetadataService.cs
index d4ea3e9cf..39f9354db 100644
--- a/MediaBrowser.Providers/Genres/GenreMetadataService.cs
+++ b/MediaBrowser.Providers/Genres/GenreMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Genres
{
diff --git a/MediaBrowser.Providers/ImagesByName/ImageUtils.cs b/MediaBrowser.Providers/ImagesByName/ImageUtils.cs
index b53348749..bbcbbda90 100644
--- a/MediaBrowser.Providers/ImagesByName/ImageUtils.cs
+++ b/MediaBrowser.Providers/ImagesByName/ImageUtils.cs
@@ -6,7 +6,9 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.ImagesByName
{
@@ -68,23 +70,26 @@ namespace MediaBrowser.Providers.ImagesByName
.Replace("/", string.Empty);
}
- public static IEnumerable<string> GetAvailableImages(string file)
+ public static IEnumerable<string> GetAvailableImages(string file, IFileSystem fileSystem)
{
- using (var reader = new StreamReader(file))
+ using (var fileStream = fileSystem.GetFileStream(file, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
{
- var lines = new List<string>();
-
- while (!reader.EndOfStream)
+ using (var reader = new StreamReader(fileStream))
{
- var text = reader.ReadLine();
+ var lines = new List<string>();
- if (!string.IsNullOrWhiteSpace(text))
+ while (!reader.EndOfStream)
{
- lines.Add(text);
+ var text = reader.ReadLine();
+
+ if (!string.IsNullOrWhiteSpace(text))
+ {
+ lines.Add(text);
+ }
}
- }
- return lines;
+ return lines;
+ }
}
}
}
diff --git a/MediaBrowser.Providers/LiveTv/AudioRecordingService.cs b/MediaBrowser.Providers/LiveTv/AudioRecordingService.cs
index 1d99a678b..df4a03cdb 100644
--- a/MediaBrowser.Providers/LiveTv/AudioRecordingService.cs
+++ b/MediaBrowser.Providers/LiveTv/AudioRecordingService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.LiveTv
{
diff --git a/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs b/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs
index 8abb99689..7b5065986 100644
--- a/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs
+++ b/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.LiveTv
{
diff --git a/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs b/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs
index b73d82c19..eaacc41fa 100644
--- a/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs
+++ b/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.LiveTv
{
diff --git a/MediaBrowser.Providers/LiveTv/VideoRecordingService.cs b/MediaBrowser.Providers/LiveTv/VideoRecordingService.cs
index 15530f8f9..a8df3c88b 100644
--- a/MediaBrowser.Providers/LiveTv/VideoRecordingService.cs
+++ b/MediaBrowser.Providers/LiveTv/VideoRecordingService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.LiveTv
{
diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs
index 767c034ee..5146df6e6 100644
--- a/MediaBrowser.Providers/Manager/ImageSaver.cs
+++ b/MediaBrowser.Providers/Manager/ImageSaver.cs
@@ -16,7 +16,8 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Manager
{
@@ -38,7 +39,7 @@ namespace MediaBrowser.Providers.Manager
private readonly ILibraryMonitor _libraryMonitor;
private readonly IFileSystem _fileSystem;
private readonly ILogger _logger;
- private readonly IMemoryStreamProvider _memoryStreamProvider;
+ private readonly IMemoryStreamFactory _memoryStreamProvider;
/// <summary>
/// Initializes a new instance of the <see cref="ImageSaver" /> class.
@@ -47,7 +48,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="libraryMonitor">The directory watchers.</param>
/// <param name="fileSystem">The file system.</param>
/// <param name="logger">The logger.</param>
- public ImageSaver(IServerConfigurationManager config, ILibraryMonitor libraryMonitor, IFileSystem fileSystem, ILogger logger, IMemoryStreamProvider memoryStreamProvider)
+ public ImageSaver(IServerConfigurationManager config, ILibraryMonitor libraryMonitor, IFileSystem fileSystem, ILogger logger, IMemoryStreamFactory memoryStreamProvider)
{
_config = config;
_libraryMonitor = libraryMonitor;
@@ -172,14 +173,14 @@ namespace MediaBrowser.Providers.Manager
try
{
- var currentFile = new FileInfo(currentPath);
+ var currentFile = _fileSystem.GetFileInfo(currentPath);
// This will fail if the file is hidden
if (currentFile.Exists)
{
- if ((currentFile.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
+ if (currentFile.IsHidden)
{
- currentFile.Attributes &= ~FileAttributes.Hidden;
+ _fileSystem.SetHidden(currentFile.FullName, false);
}
_fileSystem.DeleteFile(currentFile.FullName);
@@ -254,18 +255,22 @@ namespace MediaBrowser.Providers.Manager
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
// If the file is currently hidden we'll have to remove that or the save will fail
- var file = new FileInfo(path);
+ var file = _fileSystem.GetFileInfo(path);
// This will fail if the file is hidden
if (file.Exists)
{
- if ((file.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
+ if (file.IsHidden)
{
- file.Attributes &= ~FileAttributes.Hidden;
+ _fileSystem.SetHidden(file.FullName, false);
+ }
+ if (file.IsReadOnly)
+ {
+ _fileSystem.SetReadOnly(path, false);
}
}
- using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken)
.ConfigureAwait(false);
@@ -273,10 +278,7 @@ namespace MediaBrowser.Providers.Manager
if (_config.Configuration.SaveMetadataHidden)
{
- file.Refresh();
-
- // Add back the attribute
- file.Attributes |= FileAttributes.Hidden;
+ _fileSystem.SetHidden(file.FullName, true);
}
}
finally
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index 898fa522d..9dff243c1 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -15,8 +15,12 @@ using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.MediaInfo;
@@ -154,7 +158,7 @@ namespace MediaBrowser.Providers.Manager
{
var mimeType = MimeTypes.GetMimeType(response.Path);
- var stream = _fileSystem.GetFileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, true);
+ var stream = _fileSystem.GetFileStream(response.Path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true);
await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false);
}
@@ -370,14 +374,14 @@ namespace MediaBrowser.Providers.Manager
}
// Delete the source file
- var currentFile = new FileInfo(image.Path);
+ var currentFile = _fileSystem.GetFileInfo(image.Path);
// Deletion will fail if the file is hidden so remove the attribute first
if (currentFile.Exists)
{
- if ((currentFile.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
+ if (currentFile.IsHidden)
{
- currentFile.Attributes &= ~FileAttributes.Hidden;
+ _fileSystem.SetHidden(currentFile.FullName, false);
}
_fileSystem.DeleteFile(currentFile.FullName);
@@ -552,9 +556,7 @@ namespace MediaBrowser.Providers.Manager
switch (type)
{
case ImageType.Primary:
- return false;
- case ImageType.Thumb:
- return false;
+ return !(item is Movie || item is Series || item is Game);
default:
return true;
}
@@ -611,7 +613,7 @@ namespace MediaBrowser.Providers.Manager
{
try
{
- if (item.GetImages(imageType).Any(i => new FileInfo(i.Path).Length == response.ContentLength.Value))
+ if (item.GetImages(imageType).Any(i => _fileSystem.GetFileInfo(i.Path).Length == response.ContentLength.Value))
{
response.Content.Dispose();
continue;
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index 41cacbe0a..9c6d6a482 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -10,7 +10,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Providers;
@@ -78,16 +78,15 @@ namespace MediaBrowser.Providers.Manager
bool hasRefreshedMetadata = true;
bool hasRefreshedImages = true;
+ var isFirstRefresh = item.DateLastRefreshed == default(DateTime);
// Next run metadata providers
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
{
- var providers = GetProviders(item, refreshOptions, requiresRefresh)
+ var providers = GetProviders(item, refreshOptions, isFirstRefresh, requiresRefresh)
.ToList();
- var dateLastRefresh = item.DateLastRefreshed;
-
- if (providers.Count > 0 || dateLastRefresh == default(DateTime))
+ if (providers.Count > 0 || isFirstRefresh)
{
if (item.BeforeMetadataRefresh())
{
@@ -110,11 +109,7 @@ namespace MediaBrowser.Providers.Manager
var result = await RefreshWithProviders(metadataResult, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false);
updateType = updateType | result.UpdateType;
- if (result.Failures == 0)
- {
- hasRefreshedMetadata = true;
- }
- else
+ if (result.Failures > 0)
{
hasRefreshedMetadata = false;
}
@@ -138,19 +133,13 @@ namespace MediaBrowser.Providers.Manager
var result = await itemImageProvider.RefreshImages(itemOfType, libraryOptions, providers, refreshOptions, config, cancellationToken).ConfigureAwait(false);
updateType = updateType | result.UpdateType;
- if (result.Failures == 0)
- {
- hasRefreshedImages = true;
- }
- else
+ if (result.Failures > 0)
{
hasRefreshedImages = false;
}
}
}
- var isFirstRefresh = item.DateLastRefreshed == default(DateTime);
-
var beforeSaveResult = await BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh, updateType).ConfigureAwait(false);
updateType = updateType | beforeSaveResult;
@@ -373,15 +362,18 @@ namespace MediaBrowser.Providers.Manager
/// Gets the providers.
/// </summary>
/// <returns>IEnumerable{`0}.</returns>
- protected IEnumerable<IMetadataProvider> GetProviders(IHasMetadata item, MetadataRefreshOptions options, bool requiresRefresh)
+ protected IEnumerable<IMetadataProvider> GetProviders(IHasMetadata item, MetadataRefreshOptions options, bool isFirstRefresh, bool requiresRefresh)
{
// Get providers to refresh
var providers = ((ProviderManager)ProviderManager).GetMetadataProviders<TItemType>(item).ToList();
- var dateLastRefresh = item.DateLastRefreshed;
+ var metadataRefreshMode = options.MetadataRefreshMode;
// Run all if either of these flags are true
- var runAllProviders = options.ReplaceAllMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || dateLastRefresh == default(DateTime) || requiresRefresh;
+ var runAllProviders = options.ReplaceAllMetadata ||
+ metadataRefreshMode == MetadataRefreshMode.FullRefresh ||
+ (isFirstRefresh && metadataRefreshMode >= MetadataRefreshMode.Default) ||
+ (requiresRefresh && metadataRefreshMode >= MetadataRefreshMode.Default);
if (!runAllProviders)
{
@@ -404,6 +396,9 @@ namespace MediaBrowser.Providers.Manager
}
else
{
+ var anyRemoteProvidersChanged = providersWithChanges.OfType<IRemoteMetadataProvider>()
+ .Any();
+
providers = providers.Where(i =>
{
// If any provider reports a change, always run local ones as well
@@ -412,12 +407,14 @@ namespace MediaBrowser.Providers.Manager
return true;
}
- var anyRemoteProvidersChanged = providersWithChanges.OfType<IRemoteMetadataProvider>()
- .Any();
-
// If any remote providers changed, run them all so that priorities can be honored
if (i is IRemoteMetadataProvider)
{
+ if (options.MetadataRefreshMode == MetadataRefreshMode.ValidationOnly)
+ {
+ return false;
+ }
+
return anyRemoteProvidersChanged;
}
@@ -536,7 +533,7 @@ namespace MediaBrowser.Providers.Manager
refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport;
// Only one local provider allowed per item
- if (item.IsLocked || IsFullLocalMetadata(localItem.Item))
+ if (item.IsLocked || localItem.Item.IsLocked || IsFullLocalMetadata(localItem.Item))
{
hasLocalMetadata = true;
}
@@ -573,14 +570,16 @@ namespace MediaBrowser.Providers.Manager
{
if (refreshResult.UpdateType > ItemUpdateType.None)
{
- // If no local metadata, take data from item itself
- if (!hasLocalMetadata)
+ if (hasLocalMetadata)
+ {
+ MergeData(temp, metadata, item.LockedFields, true, true);
+ }
+ else
{
// TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields
- MergeData(metadata, temp, new List<MetadataFields>(), false, true);
+ MergeData(metadata, temp, new List<MetadataFields>(), false, false);
+ MergeData(temp, metadata, item.LockedFields, true, false);
}
-
- MergeData(temp, metadata, item.LockedFields, true, true);
}
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index dfeceed7d..a2f3d0459 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -19,8 +19,10 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Providers.Manager
@@ -64,7 +66,7 @@ namespace MediaBrowser.Providers.Manager
private IExternalId[] _externalIds;
private readonly Func<ILibraryManager> _libraryManagerFactory;
- private readonly IMemoryStreamProvider _memoryStreamProvider;
+ private readonly IMemoryStreamFactory _memoryStreamProvider;
/// <summary>
/// Initializes a new instance of the <see cref="ProviderManager" /> class.
@@ -74,7 +76,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="libraryMonitor">The directory watchers.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="fileSystem">The file system.</param>
- public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func<ILibraryManager> libraryManagerFactory, IJsonSerializer json, IMemoryStreamProvider memoryStreamProvider)
+ public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func<ILibraryManager> libraryManagerFactory, IJsonSerializer json, IMemoryStreamFactory memoryStreamProvider)
{
_logger = logManager.GetLogger("ProviderManager");
_httpClient = httpClient;
@@ -127,7 +129,8 @@ namespace MediaBrowser.Providers.Manager
{
CancellationToken = cancellationToken,
ResourcePool = resourcePool,
- Url = url
+ Url = url,
+ BufferContent = false
}).ConfigureAwait(false);
@@ -147,7 +150,7 @@ namespace MediaBrowser.Providers.Manager
throw new ArgumentNullException("source");
}
- var fileStream = _fileSystem.GetFileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true);
+ var fileStream = _fileSystem.GetFileStream(source, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite, true);
return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger, _memoryStreamProvider).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken);
}
@@ -269,17 +272,17 @@ namespace MediaBrowser.Providers.Manager
{
var options = GetMetadataOptions(item);
- return GetMetadataProvidersInternal<T>(item, options, false, true);
+ return GetMetadataProvidersInternal<T>(item, options, false, false, true);
}
- private IEnumerable<IMetadataProvider<T>> GetMetadataProvidersInternal<T>(IHasMetadata item, MetadataOptions options, bool includeDisabled, bool checkIsOwnedItem)
+ private IEnumerable<IMetadataProvider<T>> GetMetadataProvidersInternal<T>(IHasMetadata item, MetadataOptions options, bool includeDisabled, bool forceEnableInternetMetadata, bool checkIsOwnedItem)
where T : IHasMetadata
{
// Avoid implicitly captured closure
var currentOptions = options;
return _metadataProviders.OfType<IMetadataProvider<T>>()
- .Where(i => CanRefresh(i, item, currentOptions, includeDisabled, checkIsOwnedItem))
+ .Where(i => CanRefresh(i, item, currentOptions, includeDisabled, forceEnableInternetMetadata, checkIsOwnedItem))
.OrderBy(i => GetConfiguredOrder(i, options))
.ThenBy(GetDefaultOrder);
}
@@ -291,7 +294,7 @@ namespace MediaBrowser.Providers.Manager
return GetImageProviders(item, options, new ImageRefreshOptions(new DirectoryService(_logger, _fileSystem)), includeDisabled).OfType<IRemoteImageProvider>();
}
- private bool CanRefresh(IMetadataProvider provider, IHasMetadata item, MetadataOptions options, bool includeDisabled, bool checkIsOwnedItem)
+ private bool CanRefresh(IMetadataProvider provider, IHasMetadata item, MetadataOptions options, bool includeDisabled, bool forceEnableInternetMetadata, bool checkIsOwnedItem)
{
if (!includeDisabled)
{
@@ -303,7 +306,7 @@ namespace MediaBrowser.Providers.Manager
if (provider is IRemoteMetadataProvider)
{
- if (!item.IsInternetMetadataEnabled())
+ if (!forceEnableInternetMetadata && !item.IsInternetMetadataEnabled())
{
return false;
}
@@ -354,7 +357,7 @@ namespace MediaBrowser.Providers.Manager
if (provider is IRemoteImageProvider)
{
- if (!item.IsInternetMetadataEnabled())
+ if (!refreshOptions.ForceEnableInternetMetadata && !item.IsInternetMetadataEnabled())
{
return false;
}
@@ -498,7 +501,7 @@ namespace MediaBrowser.Providers.Manager
private void AddMetadataPlugins<T>(List<MetadataPlugin> list, T item, MetadataOptions options)
where T : IHasMetadata
{
- var providers = GetMetadataProvidersInternal<T>(item, options, true, false).ToList();
+ var providers = GetMetadataProvidersInternal<T>(item, options, true, false, false).ToList();
// Locals
list.AddRange(providers.Where(i => (i is ILocalMetadataProvider)).Select(i => new MetadataPlugin
@@ -558,8 +561,6 @@ namespace MediaBrowser.Providers.Manager
new MetadataOptions();
}
- private readonly ConcurrentDictionary<string, SemaphoreSlim> _fileLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
-
/// <summary>
/// Saves the metadata.
/// </summary>
@@ -583,6 +584,7 @@ namespace MediaBrowser.Providers.Manager
return SaveMetadata(item, updateType, _savers.Where(i => savers.Contains(i.Name, StringComparer.OrdinalIgnoreCase)));
}
+ private readonly SemaphoreSlim _saveLock = new SemaphoreSlim(1,1);
/// <summary>
/// Saves the metadata.
/// </summary>
@@ -612,9 +614,7 @@ namespace MediaBrowser.Providers.Manager
continue;
}
- var semaphore = _fileLocks.GetOrAdd(path, key => new SemaphoreSlim(1, 1));
-
- await semaphore.WaitAsync().ConfigureAwait(false);
+ await _saveLock.WaitAsync().ConfigureAwait(false);
try
{
@@ -627,8 +627,8 @@ namespace MediaBrowser.Providers.Manager
}
finally
{
+ _saveLock.Release();
_libraryMonitor.ReportFileSystemChangeComplete(path, false);
- semaphore.Release();
}
}
else
@@ -715,7 +715,7 @@ namespace MediaBrowser.Providers.Manager
var options = GetMetadataOptions(dummy);
- var providers = GetMetadataProvidersInternal<TItemType>(dummy, options, searchInfo.IncludeDisabledProviders, false)
+ var providers = GetMetadataProvidersInternal<TItemType>(dummy, options, searchInfo.IncludeDisabledProviders, false, false)
.OfType<IRemoteSearchProvider<TLookupType>>();
if (!string.IsNullOrEmpty(searchInfo.SearchProviderName))
@@ -861,8 +861,8 @@ namespace MediaBrowser.Providers.Manager
private readonly ConcurrentQueue<Tuple<Guid, MetadataRefreshOptions>> _refreshQueue =
new ConcurrentQueue<Tuple<Guid, MetadataRefreshOptions>>();
- private readonly object _refreshTimerLock = new object();
- private Timer _refreshTimer;
+ private readonly object _refreshQueueLock = new object();
+ private bool _isProcessingRefreshQueue;
public void QueueRefresh(Guid id, MetadataRefreshOptions options)
{
@@ -872,38 +872,18 @@ namespace MediaBrowser.Providers.Manager
}
_refreshQueue.Enqueue(new Tuple<Guid, MetadataRefreshOptions>(id, options));
- StartRefreshTimer();
- }
-
- private void StartRefreshTimer()
- {
- if (_disposed)
- {
- return;
- }
- lock (_refreshTimerLock)
+ lock (_refreshQueueLock)
{
- if (_refreshTimer == null)
+ if (!_isProcessingRefreshQueue)
{
- _refreshTimer = new Timer(RefreshTimerCallback, null, 100, Timeout.Infinite);
+ _isProcessingRefreshQueue = true;
+ Task.Run(() => StartProcessingRefreshQueue());
}
}
}
- private void StopRefreshTimer()
- {
- lock (_refreshTimerLock)
- {
- if (_refreshTimer != null)
- {
- _refreshTimer.Dispose();
- _refreshTimer = null;
- }
- }
- }
-
- private async void RefreshTimerCallback(object state)
+ private async Task StartProcessingRefreshQueue()
{
Tuple<Guid, MetadataRefreshOptions> refreshItem;
var libraryManager = _libraryManagerFactory();
@@ -937,7 +917,10 @@ namespace MediaBrowser.Providers.Manager
}
}
- StopRefreshTimer();
+ lock (_refreshQueueLock)
+ {
+ _isProcessingRefreshQueue = false;
+ }
}
private async Task RefreshItem(BaseItem item, MetadataRefreshOptions options, CancellationToken cancellationToken)
@@ -1016,7 +999,6 @@ namespace MediaBrowser.Providers.Manager
public void Dispose()
{
_disposed = true;
- StopRefreshTimer();
}
}
} \ No newline at end of file
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 8b3d1fb7e..fe554545f 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -13,6 +13,8 @@
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -23,7 +25,6 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@@ -32,7 +33,6 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Mono|AnyCPU' ">
<DebugType>none</DebugType>
@@ -41,47 +41,13 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
- <Reference Include="BDInfo, Version=1.0.5167.21152, Culture=neutral, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\BDInfo.dll</HintPath>
- </Reference>
- <Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath>
- </Reference>
- <Reference Include="DvdLib, Version=1.0.5167.21152, Culture=neutral, PublicKeyToken=7a2f3f5ec8d93575, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
- </Reference>
- <Reference Include="MoreLinq">
- <HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
- </Reference>
- <Reference Include="Patterns.Logging">
- <HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
- </Reference>
- <Reference Include="policy.2.0.taglib-sharp">
- <HintPath>..\packages\taglib.2.1.0.0\lib\policy.2.0.taglib-sharp.dll</HintPath>
- </Reference>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Net" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- <Reference Include="taglib-sharp">
- <HintPath>..\packages\taglib.2.1.0.0\lib\taglib-sharp.dll</HintPath>
- <Private>True</Private>
- </Reference>
- </ItemGroup>
- <ItemGroup>
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
+ <Compile Include="Books\AudioBookMetadataService.cs" />
+ <Compile Include="Books\AudioPodcastMetadataService.cs" />
<Compile Include="Books\BookMetadataService.cs" />
<Compile Include="BoxSets\BoxSetMetadataService.cs" />
<Compile Include="BoxSets\MovieDbBoxSetImageProvider.cs" />
@@ -116,8 +82,6 @@
<Compile Include="Movies\MovieDbSearch.cs" />
<Compile Include="Movies\MovieMetadataService.cs" />
<Compile Include="Movies\TmdbSettings.cs" />
- <Compile Include="GameGenres\GameGenreImageProvider.cs" />
- <Compile Include="Genres\GenreImageProvider.cs" />
<Compile Include="ImagesByName\ImageUtils.cs" />
<Compile Include="MediaInfo\AudioImageProvider.cs" />
<Compile Include="MediaInfo\VideoImageProvider.cs" />
@@ -149,16 +113,12 @@
<Compile Include="People\PersonMetadataService.cs" />
<Compile Include="People\MovieDbPersonProvider.cs" />
<Compile Include="Photos\PhotoAlbumMetadataService.cs" />
- <Compile Include="Photos\PhotoHelper.cs" />
<Compile Include="Photos\PhotoMetadataService.cs" />
- <Compile Include="Photos\PhotoProvider.cs" />
<Compile Include="Playlists\PlaylistMetadataService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Manager\ProviderUtils.cs" />
<Compile Include="Studios\StudiosImageProvider.cs" />
<Compile Include="Studios\StudioMetadataService.cs" />
- <Compile Include="Subtitles\ConfigurationExtension.cs" />
- <Compile Include="Subtitles\OpenSubtitleDownloader.cs" />
<Compile Include="Subtitles\SubtitleManager.cs" />
<Compile Include="TV\DummySeasonProvider.cs" />
<Compile Include="TV\EpisodeMetadataService.cs" />
@@ -180,7 +140,6 @@
<Compile Include="TV\SeasonMetadataService.cs" />
<Compile Include="TV\TheTVDB\TvdbEpisodeProvider.cs" />
<Compile Include="TV\TheTVDB\TvdbSeriesProvider.cs" />
- <Compile Include="TV\SeriesPostScanTask.cs" />
<Compile Include="TV\TheTVDB\TvdbPrescanTask.cs" />
<Compile Include="TV\TvExternalIds.cs" />
<Compile Include="Users\UserMetadataService.cs" />
@@ -188,6 +147,10 @@
<Compile Include="Years\YearMetadataService.cs" />
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\DvdLib\DvdLib.csproj">
+ <Project>{713f42b5-878e-499d-a878-e4c652b1d5e8}</Project>
+ <Name>DvdLib</Name>
+ </ProjectReference>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
<Project>{9142EEFA-7570-41E1-BFCC-468BB571AF2F}</Project>
<Name>MediaBrowser.Common</Name>
@@ -200,16 +163,9 @@
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
<Name>MediaBrowser.Model</Name>
</ProjectReference>
- <ProjectReference Include="..\OpenSubtitlesHandler\OpenSubtitlesHandler.csproj">
- <Project>{4a4402d4-e910-443b-b8fc-2c18286a2ca0}</Project>
- <Name>OpenSubtitlesHandler</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <None Include="packages.config" />
</ItemGroup>
<ItemGroup />
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.nuget.targets b/MediaBrowser.Providers/MediaBrowser.Providers.nuget.targets
new file mode 100644
index 000000000..e69ce0e64
--- /dev/null
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.nuget.targets
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Target Name="EmitMSBuildWarning" BeforeTargets="Build">
+ <Warning Text="Packages containing MSBuild targets and props files cannot be fully installed in projects targeting multiple frameworks. The MSBuild targets and props files have been ignored." />
+ </Target>
+</Project> \ No newline at end of file
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index 68fc80371..d65084287 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -6,13 +6,12 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
-using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.MediaInfo
{
@@ -21,8 +20,6 @@ namespace MediaBrowser.Providers.MediaInfo
/// </summary>
public class AudioImageProvider : IDynamicImageProvider, IHasItemChangeMonitor
{
- private readonly ConcurrentDictionary<string, SemaphoreSlim> _locks = new ConcurrentDictionary<string, SemaphoreSlim>();
-
private readonly IMediaEncoder _mediaEncoder;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
@@ -65,41 +62,25 @@ namespace MediaBrowser.Providers.MediaInfo
if (!_fileSystem.FileExists(path))
{
- var semaphore = GetLock(path);
-
- // Acquire a lock
- await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- try
- {
- // Check again in case it was saved while waiting for the lock
- if (!_fileSystem.FileExists(path))
- {
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
-
- var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ??
- imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ??
- imageStreams.FirstOrDefault();
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
- var imageStreamIndex = imageStream == null ? (int?)null : imageStream.Index;
+ var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ??
+ imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ??
+ imageStreams.FirstOrDefault();
- var tempFile = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false);
+ var imageStreamIndex = imageStream == null ? (int?)null : imageStream.Index;
- File.Copy(tempFile, path, true);
+ var tempFile = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false);
- try
- {
- File.Delete(tempFile);
- }
- catch
- {
+ _fileSystem.CopyFile(tempFile, path, true);
- }
- }
+ try
+ {
+ _fileSystem.DeleteFile(tempFile);
}
- finally
+ catch
{
- semaphore.Release();
+
}
}
@@ -143,16 +124,6 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- /// <summary>
- /// Gets the lock.
- /// </summary>
- /// <param name="filename">The filename.</param>
- /// <returns>SemaphoreSlim.</returns>
- private SemaphoreSlim GetLock(string filename)
- {
- return _locks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1));
- }
-
public string Name
{
get { return "Image Extractor"; }
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
index d255110fb..eaffc12d7 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
@@ -7,7 +7,6 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
@@ -21,7 +20,10 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.MediaInfo
{
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index be0b2ca6d..0a070d348 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -7,7 +7,6 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
@@ -26,7 +25,10 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.MediaInfo
{
@@ -132,23 +134,6 @@ namespace MediaBrowser.Providers.MediaInfo
{
cancellationToken.ThrowIfCancellationRequested();
- //var idString = item.Id.ToString("N");
- //var cachePath = Path.Combine(_appPaths.CachePath,
- // "ffprobe-video",
- // idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");
-
- try
- {
- //return _json.DeserializeFromFile<Model.MediaInfo.MediaInfo>(cachePath);
- }
- catch (FileNotFoundException)
- {
-
- }
- catch (DirectoryNotFoundException)
- {
- }
-
var protocol = item.LocationType == LocationType.Remote
? MediaProtocol.Http
: MediaProtocol.File;
@@ -218,7 +203,6 @@ namespace MediaBrowser.Providers.MediaInfo
var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
- video.VideoBitRate = videoStream == null ? null : videoStream.BitRate;
video.DefaultVideoStreamIndex = videoStream == null ? (int?)null : videoStream.Index;
video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle);
@@ -605,7 +589,7 @@ namespace MediaBrowser.Providers.MediaInfo
private void FetchFromDvdLib(Video item, IIsoMount mount)
{
var path = mount == null ? item.Path : mount.MountedPath;
- var dvd = new Dvd(path);
+ var dvd = new Dvd(path, _fileSystem);
var primaryTitle = dvd.Titles.OrderByDescending(GetRuntime).FirstOrDefault();
@@ -653,7 +637,7 @@ namespace MediaBrowser.Providers.MediaInfo
/// <returns>System.Nullable{IsoType}.</returns>
private IsoType? DetermineIsoType(IIsoMount isoMount)
{
- var fileSystemEntries = Directory.EnumerateFileSystemEntries(isoMount.MountedPath).Select(Path.GetFileName).ToList();
+ var fileSystemEntries = _fileSystem.GetFileSystemEntryPaths(isoMount.MountedPath).Select(Path.GetFileName).ToList();
if (fileSystemEntries.Contains("video_ts", StringComparer.OrdinalIgnoreCase) ||
fileSystemEntries.Contains("VIDEO_TS.IFO", StringComparer.OrdinalIgnoreCase))
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
index 9ae8413d1..b69e37136 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
@@ -139,7 +139,7 @@ namespace MediaBrowser.Providers.MediaInfo
request.IndexNumberEnd = episode.IndexNumberEnd;
request.SeriesName = episode.SeriesName;
}
-
+
try
{
var searchResults = await _subtitleManager.SearchSubtitles(request, cancellationToken).ConfigureAwait(false);
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
index 024171f40..313feda52 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
@@ -1,13 +1,15 @@
using MediaBrowser.Model.Extensions;
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.MediaInfo
{
@@ -43,6 +45,11 @@ namespace MediaBrowser.Providers.MediaInfo
var codec = Path.GetExtension(fullName).ToLower().TrimStart('.');
+ if (string.Equals(codec, "txt", StringComparison.OrdinalIgnoreCase))
+ {
+ codec = "srt";
+ }
+
// If the subtitle file matches the video file name
if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{
@@ -72,9 +79,9 @@ namespace MediaBrowser.Providers.MediaInfo
// Try to translate to three character code
// Be flexible and check against both the full and three character versions
var culture = _localization.GetCultures()
- .FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) ||
- string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) ||
- string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) ||
+ .FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) ||
string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase));
if (culture != null)
@@ -117,7 +124,7 @@ namespace MediaBrowser.Providers.MediaInfo
{
get
{
- return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami" };
+ return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami", ".txt" };
}
}
@@ -136,7 +143,7 @@ namespace MediaBrowser.Providers.MediaInfo
return files.Where(i =>
{
- if (!i.Attributes.HasFlag(FileAttributes.Directory) &&
+ if (!i.IsDirectory &&
SubtitleExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
{
var fileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(i);
diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
index 45d1c3d80..ca701b70f 100644
--- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
@@ -13,7 +13,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
namespace MediaBrowser.Providers.MediaInfo
{
diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
index 2a40e4d85..dd2cad1f9 100644
--- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
+++ b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
@@ -19,7 +19,9 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Providers.TV;
@@ -116,7 +118,7 @@ namespace MediaBrowser.Providers.Movies
{
// No biggie. Don't blow up
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
// No biggie. Don't blow up
}
@@ -220,8 +222,7 @@ namespace MediaBrowser.Providers.Movies
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
+ Url = url
});
}
@@ -284,11 +285,12 @@ namespace MediaBrowser.Providers.Movies
{
Url = url,
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool,
- CancellationToken = cancellationToken
+ CancellationToken = cancellationToken,
+ BufferContent = true
}).ConfigureAwait(false))
{
- using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await response.CopyToAsync(fileStream).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
index 82a2dfbe9..6788bdc9c 100644
--- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
+++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
@@ -13,7 +13,9 @@ using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Extensions;
namespace MediaBrowser.Providers.Movies
@@ -24,16 +26,16 @@ namespace MediaBrowser.Providers.Movies
private readonly ILogger _logger;
private readonly IJsonSerializer _jsonSerializer;
private readonly ILibraryManager _libraryManager;
- private readonly IFileSystem _fileSystem;
+ private readonly IFileSystem _fileSystem;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- public GenericMovieDbInfo(ILogger logger, IJsonSerializer jsonSerializer, ILibraryManager libraryManager, IFileSystem fileSystem)
+ public GenericMovieDbInfo(ILogger logger, IJsonSerializer jsonSerializer, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_logger = logger;
_jsonSerializer = jsonSerializer;
_libraryManager = libraryManager;
- _fileSystem = fileSystem;
+ _fileSystem = fileSystem;
}
public async Task<MetadataResult<T>> GetMetadata(ItemLookupInfo itemId, CancellationToken cancellationToken)
@@ -269,6 +271,8 @@ namespace MediaBrowser.Providers.Movies
//and the rest from crew
if (movieData.casts != null && movieData.casts.crew != null)
{
+ var keepTypes = new[] { PersonType.Director, PersonType.Writer, PersonType.Producer };
+
foreach (var person in movieData.casts.crew)
{
// Normalize this
@@ -278,6 +282,12 @@ namespace MediaBrowser.Providers.Movies
type = PersonType.Writer;
}
+ if (!keepTypes.Contains(type ?? string.Empty, StringComparer.OrdinalIgnoreCase) &&
+ !keepTypes.Contains(person.job ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
var personInfo = new PersonInfo
{
Name = person.name.Trim(),
diff --git a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs
index 49f341f26..59b4b5198 100644
--- a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs
@@ -14,6 +14,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Movies
{
@@ -21,11 +22,13 @@ namespace MediaBrowser.Providers.Movies
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
+ private readonly IFileSystem _fileSystem;
- public MovieDbImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient)
+ public MovieDbImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
+ _fileSystem = fileSystem;
}
public string Name
@@ -196,7 +199,7 @@ namespace MediaBrowser.Providers.Movies
if (!string.IsNullOrEmpty(path))
{
- var fileInfo = new FileInfo(path);
+ var fileInfo = _fileSystem.GetFileInfo(path);
if (fileInfo.Exists)
{
@@ -217,8 +220,7 @@ namespace MediaBrowser.Providers.Movies
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index b0d119ff9..8e4b86519 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -17,8 +16,11 @@ using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Common;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Net;
namespace MediaBrowser.Providers.Movies
@@ -432,6 +434,7 @@ namespace MediaBrowser.Providers.Movies
options.ResourcePool = MovieDbResourcePool;
_lastRequestTicks = DateTime.UtcNow.Ticks;
+ options.BufferContent = true;
options.UserAgent = "Emby/" + _appHost.ApplicationVersion;
return await _httpClient.Get(options).ConfigureAwait(false);
@@ -655,8 +658,7 @@ namespace MediaBrowser.Providers.Movies
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = MovieDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs
index 81df7b805..36297914d 100644
--- a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs
@@ -46,8 +46,7 @@ namespace MediaBrowser.Providers.Movies
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/Movies/MovieMetadataService.cs b/MediaBrowser.Providers/Movies/MovieMetadataService.cs
index 83be9ca6f..2187d6df1 100644
--- a/MediaBrowser.Providers/Movies/MovieMetadataService.cs
+++ b/MediaBrowser.Providers/Movies/MovieMetadataService.cs
@@ -6,8 +6,10 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
namespace MediaBrowser.Providers.Movies
{
diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
index 4f87b2036..e5dbba902 100644
--- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs
+++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
@@ -9,7 +9,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Music
{
diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
index b2f975b13..1bd427ac9 100644
--- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs
+++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
@@ -9,7 +9,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Music
{
diff --git a/MediaBrowser.Providers/Music/AudioDbAlbumImageProvider.cs b/MediaBrowser.Providers/Music/AudioDbAlbumImageProvider.cs
index efaa730b2..c13d19c43 100644
--- a/MediaBrowser.Providers/Music/AudioDbAlbumImageProvider.cs
+++ b/MediaBrowser.Providers/Music/AudioDbAlbumImageProvider.cs
@@ -87,8 +87,7 @@ namespace MediaBrowser.Providers.Music
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = AudioDbArtistProvider.Current.AudioDbResourcePool
+ Url = url
});
}
diff --git a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
index 5963e90e2..3f969b609 100644
--- a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
@@ -13,7 +13,9 @@ using System.Globalization;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Music
{
@@ -162,12 +164,11 @@ namespace MediaBrowser.Providers.Music
using (var response = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = AudioDbArtistProvider.Current.AudioDbResourcePool,
CancellationToken = cancellationToken
}).ConfigureAwait(false))
{
- using (var xmlFileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/Music/AudioDbArtistImageProvider.cs b/MediaBrowser.Providers/Music/AudioDbArtistImageProvider.cs
index 2fcc14c83..6ca1d83d8 100644
--- a/MediaBrowser.Providers/Music/AudioDbArtistImageProvider.cs
+++ b/MediaBrowser.Providers/Music/AudioDbArtistImageProvider.cs
@@ -129,8 +129,7 @@ namespace MediaBrowser.Providers.Music
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = AudioDbArtistProvider.Current.AudioDbResourcePool
+ Url = url
});
}
diff --git a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs
index 8bcb01228..0f0c31e6e 100644
--- a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs
@@ -12,7 +12,9 @@ using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Music
{
@@ -150,13 +152,14 @@ namespace MediaBrowser.Providers.Music
{
Url = url,
ResourcePool = AudioDbResourcePool,
- CancellationToken = cancellationToken
+ CancellationToken = cancellationToken,
+ BufferContent = true
}).ConfigureAwait(false))
{
_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
- using (var xmlFileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await response.CopyToAsync(xmlFileStream).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/Music/AudioMetadataService.cs b/MediaBrowser.Providers/Music/AudioMetadataService.cs
index 67ddd8981..faa8bb3ad 100644
--- a/MediaBrowser.Providers/Music/AudioMetadataService.cs
+++ b/MediaBrowser.Providers/Music/AudioMetadataService.cs
@@ -7,7 +7,9 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
using System.Linq;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Music
{
diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
index 2f09d64af..d22929664 100644
--- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
@@ -14,7 +14,9 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Providers.Music
@@ -92,7 +94,7 @@ namespace MediaBrowser.Providers.Music
{
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
}
@@ -209,8 +211,7 @@ namespace MediaBrowser.Providers.Music
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
index 6afa80507..6fd0d82bd 100644
--- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
@@ -17,7 +17,9 @@ using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
@@ -96,7 +98,7 @@ namespace MediaBrowser.Providers.Music
{
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
}
@@ -204,8 +206,7 @@ namespace MediaBrowser.Providers.Music
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = FanArtResourcePool
+ Url = url
});
}
@@ -255,11 +256,12 @@ namespace MediaBrowser.Providers.Music
{
Url = url,
ResourcePool = FanArtResourcePool,
- CancellationToken = cancellationToken
+ CancellationToken = cancellationToken,
+ BufferContent = true
}).ConfigureAwait(false))
{
- using (var saveFileStream = _fileSystem.GetFileStream(jsonPath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ using (var saveFileStream = _fileSystem.GetFileStream(jsonPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await response.CopyToAsync(saveFileStream).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
index 9ed8f0a00..ec31824db 100644
--- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
@@ -7,6 +7,7 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
@@ -15,6 +16,7 @@ using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.Providers.Music
{
@@ -26,15 +28,17 @@ namespace MediaBrowser.Providers.Music
private readonly IApplicationHost _appHost;
private readonly ILogger _logger;
private readonly IJsonSerializer _json;
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
public static string MusicBrainzBaseUrl = "https://www.musicbrainz.org";
- public MusicBrainzAlbumProvider(IHttpClient httpClient, IApplicationHost appHost, ILogger logger, IJsonSerializer json)
+ public MusicBrainzAlbumProvider(IHttpClient httpClient, IApplicationHost appHost, ILogger logger, IJsonSerializer json, IXmlReaderSettingsFactory xmlSettings)
{
_httpClient = httpClient;
_appHost = appHost;
_logger = logger;
_json = json;
+ _xmlSettings = xmlSettings;
Current = this;
}
@@ -71,35 +75,50 @@ namespace MediaBrowser.Providers.Music
if (!string.IsNullOrWhiteSpace(url))
{
- var doc = await GetMusicBrainzResponse(url, isNameSearch, cancellationToken).ConfigureAwait(false);
-
- return GetResultsFromResponse(doc);
+ using (var stream = await GetMusicBrainzResponse(url, isNameSearch, cancellationToken).ConfigureAwait(false))
+ {
+ return GetResultsFromResponse(stream);
+ }
}
return new List<RemoteSearchResult>();
}
- private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlDocument doc)
+ private List<RemoteSearchResult> GetResultsFromResponse(Stream stream)
{
- return ReleaseResult.Parse(doc).Select(i =>
+ using (var oReader = new StreamReader(stream, Encoding.UTF8))
{
- var result = new RemoteSearchResult
- {
- Name = i.Title,
- ProductionYear = i.Year
- };
+ var settings = _xmlSettings.Create(false);
- if (!string.IsNullOrWhiteSpace(i.ReleaseId))
- {
- result.SetProviderId(MetadataProviders.MusicBrainzAlbum, i.ReleaseId);
- }
- if (!string.IsNullOrWhiteSpace(i.ReleaseGroupId))
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
+
+ using (var reader = XmlReader.Create(oReader, settings))
{
- result.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, i.ReleaseGroupId);
- }
+ var results = ReleaseResult.Parse(reader);
- return result;
- });
+ return results.Select(i =>
+ {
+ var result = new RemoteSearchResult
+ {
+ Name = i.Title,
+ ProductionYear = i.Year
+ };
+
+ if (!string.IsNullOrWhiteSpace(i.ReleaseId))
+ {
+ result.SetProviderId(MetadataProviders.MusicBrainzAlbum, i.ReleaseId);
+ }
+ if (!string.IsNullOrWhiteSpace(i.ReleaseGroupId))
+ {
+ result.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, i.ReleaseGroupId);
+ }
+
+ return result;
+ }).ToList();
+ }
+ }
}
public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken)
@@ -191,9 +210,22 @@ namespace MediaBrowser.Providers.Music
WebUtility.UrlEncode(albumName),
artistId);
- var doc = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
+ using (var stream = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
+ {
+ using (var oReader = new StreamReader(stream, Encoding.UTF8))
+ {
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
- return ReleaseResult.Parse(doc, 1).FirstOrDefault();
+ using (var reader = XmlReader.Create(oReader, settings))
+ {
+ return ReleaseResult.Parse(reader).FirstOrDefault();
+ }
+ }
+ }
}
private async Task<ReleaseResult> GetReleaseResultByArtistName(string albumName, string artistName, CancellationToken cancellationToken)
@@ -202,9 +234,22 @@ namespace MediaBrowser.Providers.Music
WebUtility.UrlEncode(albumName),
WebUtility.UrlEncode(artistName));
- var doc = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
+ using (var stream = await GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
+ {
+ using (var oReader = new StreamReader(stream, Encoding.UTF8))
+ {
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
- return ReleaseResult.Parse(doc, 1).FirstOrDefault();
+ using (var reader = XmlReader.Create(oReader, settings))
+ {
+ return ReleaseResult.Parse(reader).FirstOrDefault();
+ }
+ }
+ }
}
private class ReleaseResult
@@ -215,108 +260,154 @@ namespace MediaBrowser.Providers.Music
public string Overview;
public int? Year;
- public static List<ReleaseResult> Parse(XmlDocument doc, int? limit = null)
+ public static List<ReleaseResult> Parse(XmlReader reader)
{
- var docElem = doc.DocumentElement;
- var list = new List<ReleaseResult>();
-
- if (docElem == null)
- {
- return list;
- }
-
- var releaseList = docElem.FirstChild;
- if (releaseList == null)
- {
- return list;
- }
+ reader.MoveToContent();
+ reader.Read();
- var nodes = releaseList.ChildNodes;
-
- if (nodes != null)
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- foreach (var node in nodes.Cast<XmlNode>())
+ if (reader.NodeType == XmlNodeType.Element)
{
- if (string.Equals(node.Name, "release", StringComparison.OrdinalIgnoreCase))
+ switch (reader.Name)
{
- var releaseId = node.Attributes["id"].Value;
- var releaseGroupId = GetReleaseGroupIdFromReleaseNode(node);
-
- list.Add(new ReleaseResult
- {
- ReleaseId = releaseId,
- ReleaseGroupId = releaseGroupId,
- Title = GetValueFromReleaseNode(node, "title"),
- Overview = GetValueFromReleaseNode(node, "annotation"),
- Year = GetYearFromReleaseNode(node, "date")
- });
-
- if (limit.HasValue && list.Count >= limit.Value)
- {
- break;
- }
+ case "release-list":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subReader = reader.ReadSubtree())
+ {
+ return ParseReleaseList(subReader);
+ }
+ }
+ default:
+ {
+ reader.Skip();
+ break;
+ }
}
}
+ else
+ {
+ reader.Read();
+ }
}
- return list;
+ return new List<ReleaseResult>();
}
- private static int? GetYearFromReleaseNode(XmlNode node, string name)
+ private static List<ReleaseResult> ParseReleaseList(XmlReader reader)
{
- var subNodes = node.ChildNodes;
- if (subNodes != null)
+ var list = new List<ReleaseResult>();
+
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- foreach (var subNode in subNodes.Cast<XmlNode>())
+ if (reader.NodeType == XmlNodeType.Element)
{
- if (string.Equals(subNode.Name, name, StringComparison.OrdinalIgnoreCase))
+ switch (reader.Name)
{
- DateTime date;
- if (DateTime.TryParse(subNode.InnerText, out date))
- {
- return date.Year;
- }
-
- return null;
+ case "release":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ var releaseId = reader.GetAttribute("id");
+
+ using (var subReader = reader.ReadSubtree())
+ {
+ var release = ParseRelease(subReader, releaseId);
+ if (release != null)
+ {
+ list.Add(release);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ reader.Skip();
+ break;
+ }
}
}
+ else
+ {
+ reader.Read();
+ }
}
- return null;
+ return list;
}
- private static string GetValueFromReleaseNode(XmlNode node, string name)
+ private static ReleaseResult ParseRelease(XmlReader reader, string releaseId)
{
- var subNodes = node.ChildNodes;
- if (subNodes != null)
+ var result = new ReleaseResult
{
- foreach (var subNode in subNodes.Cast<XmlNode>())
- {
- if (string.Equals(subNode.Name, name, StringComparison.OrdinalIgnoreCase))
- {
- return subNode.InnerText;
- }
- }
- }
+ ReleaseId = releaseId
+ };
- return null;
- }
+ reader.MoveToContent();
+ reader.Read();
- private static string GetReleaseGroupIdFromReleaseNode(XmlNode node)
- {
- var subNodes = node.ChildNodes;
- if (subNodes != null)
+ // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- foreach (var subNode in subNodes.Cast<XmlNode>())
+ if (reader.NodeType == XmlNodeType.Element)
{
- if (string.Equals(subNode.Name, "release-group", StringComparison.OrdinalIgnoreCase))
+ switch (reader.Name)
{
- return subNode.Attributes["id"].Value;
+ case "title":
+ {
+ result.Title = reader.ReadElementContentAsString();
+ break;
+ }
+ case "date":
+ {
+ var val = reader.ReadElementContentAsString();
+ DateTime date;
+ if (DateTime.TryParse(val, out date))
+ {
+ result.Year = date.Year;
+ }
+ break;
+ }
+ case "annotation":
+ {
+ result.Overview = reader.ReadElementContentAsString();
+ break;
+ }
+ case "release-group":
+ {
+ result.ReleaseGroupId = reader.GetAttribute("id");
+ reader.Skip();
+ break;
+ }
+ default:
+ {
+ reader.Skip();
+ break;
+ }
}
}
+ else
+ {
+ reader.Read();
+ }
}
- return null;
+ return result;
}
}
@@ -330,33 +421,87 @@ namespace MediaBrowser.Providers.Music
{
var url = string.Format("/ws/2/release-group/?query=reid:{0}", releaseEntryId);
- var doc = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false);
+ using (var stream = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false))
+ {
+ using (var oReader = new StreamReader(stream, Encoding.UTF8))
+ {
+ var settings = _xmlSettings.Create(false);
- var docElem = doc.DocumentElement;
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
- if (docElem == null)
- {
- return null;
- }
+ using (var reader = XmlReader.Create(oReader, settings))
+ {
+ reader.MoveToContent();
+ reader.Read();
- var releaseList = docElem.FirstChild;
- if (releaseList == null)
- {
- return null;
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "release-group-list":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subReader = reader.ReadSubtree())
+ {
+ return GetFirstReleaseGroupId(subReader);
+ }
+ }
+ default:
+ {
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ return null;
+ }
+ }
}
+ }
- var nodes = releaseList.ChildNodes;
+ private string GetFirstReleaseGroupId(XmlReader reader)
+ {
+ reader.MoveToContent();
+ reader.Read();
- if (nodes != null)
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- foreach (var node in nodes.Cast<XmlNode>())
+ if (reader.NodeType == XmlNodeType.Element)
{
- if (string.Equals(node.Name, "release-group", StringComparison.OrdinalIgnoreCase))
+ switch (reader.Name)
{
- return node.Attributes["id"].Value;
+ case "release-group":
+ {
+ return reader.GetAttribute("id");
+ }
+ default:
+ {
+ reader.Skip();
+ break;
+ }
}
}
+ else
+ {
+ reader.Read();
+ }
}
+
return null;
}
@@ -402,7 +547,9 @@ namespace MediaBrowser.Providers.Music
using (var stream = await _httpClient.Get(options).ConfigureAwait(false))
{
- list = _json.DeserializeFromStream<List<MbzUrl>>(stream);
+ var results = _json.DeserializeFromStream<List<MbzUrl>>(stream);
+
+ list = results;
}
_lastMbzUrlQueryTicks = DateTime.UtcNow.Ticks;
}
@@ -432,37 +579,30 @@ namespace MediaBrowser.Providers.Music
/// <param name="isSearch">if set to <c>true</c> [is search].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{XmlDocument}.</returns>
- internal async Task<XmlDocument> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
+ internal async Task<Stream> GetMusicBrainzResponse(string url, bool isSearch, CancellationToken cancellationToken)
{
var urlInfo = await GetMbzUrl().ConfigureAwait(false);
+ var throttleMs = urlInfo.throttleMs;
- if (urlInfo.throttleMs > 0)
+ if (throttleMs > 0)
{
// MusicBrainz is extremely adamant about limiting to one request per second
- await Task.Delay(urlInfo.throttleMs, cancellationToken).ConfigureAwait(false);
+ _logger.Debug("Throttling MusicBrainz by {0}ms", throttleMs.ToString(CultureInfo.InvariantCulture));
+ await Task.Delay(throttleMs, cancellationToken).ConfigureAwait(false);
}
url = urlInfo.url.TrimEnd('/') + url;
- var doc = new XmlDocument();
-
var options = new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,
UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion,
- ResourcePool = _musicBrainzResourcePool
+ ResourcePool = _musicBrainzResourcePool,
+ BufferContent = throttleMs > 0
};
- using (var xml = await _httpClient.Get(options).ConfigureAwait(false))
- {
- using (var oReader = new StreamReader(xml, Encoding.UTF8))
- {
- doc.Load(oReader);
- }
- }
-
- return doc;
+ return await _httpClient.Get(options).ConfigureAwait(false);
}
public int Order
diff --git a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs
index 88128bdc7..1a2b13e94 100644
--- a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs
@@ -6,17 +6,27 @@ using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
+using MediaBrowser.Controller.Extensions;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.Providers.Music
{
public class MusicBrainzArtistProvider : IRemoteMetadataProvider<MusicArtist, ArtistInfo>
{
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
+
+ public MusicBrainzArtistProvider(IXmlReaderSettingsFactory xmlSettings)
+ {
+ _xmlSettings = xmlSettings;
+ }
+
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
{
var musicBrainzId = searchInfo.GetMusicBrainzArtistId();
@@ -25,10 +35,11 @@ namespace MediaBrowser.Providers.Music
{
var url = string.Format("/ws/2/artist/?query=arid:{0}", musicBrainzId);
- var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken)
- .ConfigureAwait(false);
-
- return GetResultsFromResponse(doc);
+ using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken)
+ .ConfigureAwait(false))
+ {
+ return GetResultsFromResponse(stream);
+ }
}
else
{
@@ -37,13 +48,14 @@ namespace MediaBrowser.Providers.Music
var url = String.Format("/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch));
- var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
-
- var results = GetResultsFromResponse(doc).ToList();
-
- if (results.Count > 0)
+ using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
{
- return results;
+ var results = GetResultsFromResponse(stream).ToList();
+
+ if (results.Count > 0)
+ {
+ return results;
+ }
}
if (HasDiacritics(searchInfo.Name))
@@ -51,73 +63,165 @@ namespace MediaBrowser.Providers.Music
// Try again using the search with accent characters url
url = String.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
- doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false);
-
- return GetResultsFromResponse(doc);
+ using (var stream = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false))
+ {
+ return GetResultsFromResponse(stream);
+ }
}
}
return new List<RemoteSearchResult>();
}
- private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlDocument doc)
+ private IEnumerable<RemoteSearchResult> GetResultsFromResponse(Stream stream)
{
- var list = new List<RemoteSearchResult>();
+ using (var oReader = new StreamReader(stream, Encoding.UTF8))
+ {
+ var settings = _xmlSettings.Create(false);
- var docElem = doc.DocumentElement;
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
- if (docElem == null)
- {
- return list;
- }
+ using (var reader = XmlReader.Create(oReader, settings))
+ {
+ reader.MoveToContent();
+ reader.Read();
- var artistList = docElem.FirstChild;
- if (artistList == null)
- {
- return list;
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "artist-list":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subReader = reader.ReadSubtree())
+ {
+ return ParseArtistList(subReader);
+ }
+ }
+ default:
+ {
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+
+ return new List<RemoteSearchResult>();
+ }
}
+ }
- var nodes = artistList.ChildNodes;
+ private IEnumerable<RemoteSearchResult> ParseArtistList(XmlReader reader)
+ {
+ var list = new List<RemoteSearchResult>();
- if (nodes != null)
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- foreach (var node in nodes.Cast<XmlNode>())
+ if (reader.NodeType == XmlNodeType.Element)
{
- if (node.Attributes != null)
+ switch (reader.Name)
{
- string name = null;
- string overview = null;
- string mbzId = node.Attributes["id"].Value;
-
- foreach (var child in node.ChildNodes.Cast<XmlNode>())
- {
- if (string.Equals(child.Name, "name", StringComparison.OrdinalIgnoreCase))
+ case "artist":
{
- name = child.InnerText;
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ var mbzId = reader.GetAttribute("id");
+
+ using (var subReader = reader.ReadSubtree())
+ {
+ var artist = ParseArtist(subReader, mbzId);
+ if (artist != null)
+ {
+ list.Add(artist);
+ }
+ }
+ break;
}
- if (string.Equals(child.Name, "annotation", StringComparison.OrdinalIgnoreCase))
+ default:
{
- overview = child.InnerText;
+ reader.Skip();
+ break;
}
- }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
- if (!string.IsNullOrWhiteSpace(mbzId) && !string.IsNullOrWhiteSpace(name))
- {
- var result = new RemoteSearchResult
- {
- Name = name,
- Overview = overview
- };
+ return list;
+ }
- result.SetProviderId(MetadataProviders.MusicBrainzArtist, mbzId);
+ private RemoteSearchResult ParseArtist(XmlReader reader, string artistId)
+ {
+ var result = new RemoteSearchResult();
- list.Add(result);
- }
+ reader.MoveToContent();
+ reader.Read();
+
+ // http://stackoverflow.com/questions/2299632/why-does-xmlreader-skip-every-other-element-if-there-is-no-whitespace-separator
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "name":
+ {
+ result.Name = reader.ReadElementContentAsString();
+ break;
+ }
+ case "annotation":
+ {
+ result.Overview = reader.ReadElementContentAsString();
+ break;
+ }
+ default:
+ {
+ // there is sort-name if ever needed
+ reader.Skip();
+ break;
+ }
}
}
+ else
+ {
+ reader.Read();
+ }
}
- return list;
+ result.SetProviderId(MetadataProviders.MusicBrainzArtist, artistId);
+
+ if (string.IsNullOrWhiteSpace(artistId) || string.IsNullOrWhiteSpace(result.Name))
+ {
+ return null;
+ }
+
+ return result;
}
public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken)
@@ -159,21 +263,7 @@ namespace MediaBrowser.Providers.Music
/// <returns><c>true</c> if the specified text has diacritics; otherwise, <c>false</c>.</returns>
private bool HasDiacritics(string text)
{
- return !String.Equals(text, RemoveDiacritics(text), StringComparison.Ordinal);
- }
-
- /// <summary>
- /// Removes the diacritics.
- /// </summary>
- /// <param name="text">The text.</param>
- /// <returns>System.String.</returns>
- private string RemoveDiacritics(string text)
- {
- return String.Concat(
- text.Normalize(NormalizationForm.FormD)
- .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) !=
- UnicodeCategory.NonSpacingMark)
- ).Normalize(NormalizationForm.FormC);
+ return !String.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal);
}
/// <summary>
diff --git a/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs b/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs
index a50c07721..f46b6b128 100644
--- a/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs
+++ b/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs
@@ -7,7 +7,9 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
using System.Linq;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Music
{
diff --git a/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs b/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs
index d7b96271b..f1ffd09db 100644
--- a/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs
+++ b/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.MusicGenres
{
diff --git a/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs
index 90d172bc2..812f0443e 100644
--- a/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs
@@ -1,4 +1,4 @@
-using CommonIO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -12,6 +12,8 @@ using MediaBrowser.Model.Serialization;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
namespace MediaBrowser.Providers.Omdb
{
@@ -68,9 +70,7 @@ namespace MediaBrowser.Providers.Omdb
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = OmdbProvider.ResourcePool
-
+ Url = url
});
}
diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
index 428bde2f2..db551b763 100644
--- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
@@ -1,4 +1,4 @@
-using CommonIO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -18,6 +18,8 @@ using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
namespace MediaBrowser.Providers.Omdb
{
@@ -129,7 +131,8 @@ namespace MediaBrowser.Providers.Omdb
{
Url = url,
ResourcePool = OmdbProvider.ResourcePool,
- CancellationToken = cancellationToken
+ CancellationToken = cancellationToken,
+ BufferContent = true
}).ConfigureAwait(false))
{
@@ -294,8 +297,7 @@ namespace MediaBrowser.Providers.Omdb
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = OmdbProvider.ResourcePool
+ Url = url
});
}
diff --git a/MediaBrowser.Providers/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Omdb/OmdbProvider.cs
index 9c7a16fab..721e31b07 100644
--- a/MediaBrowser.Providers/Omdb/OmdbProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbProvider.cs
@@ -1,4 +1,4 @@
-using CommonIO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -14,6 +14,8 @@ using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
namespace MediaBrowser.Providers.Omdb
{
@@ -35,7 +37,7 @@ namespace MediaBrowser.Providers.Omdb
}
public async Task Fetch<T>(MetadataResult<T> itemResult, string imdbId, string language, string country, CancellationToken cancellationToken)
- where T :BaseItem
+ where T : BaseItem
{
if (string.IsNullOrWhiteSpace(imdbId))
{
@@ -46,25 +48,25 @@ namespace MediaBrowser.Providers.Omdb
var result = await GetRootObject(imdbId, cancellationToken);
- // Only take the name and rating if the user's language is set to english, since Omdb has no localization
- if (string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
- {
- item.Name = result.Title;
+ // Only take the name and rating if the user's language is set to english, since Omdb has no localization
+ if (string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
+ {
+ item.Name = result.Title;
- if (string.Equals(country, "us", StringComparison.OrdinalIgnoreCase))
- {
- item.OfficialRating = result.Rated;
- }
+ if (string.Equals(country, "us", StringComparison.OrdinalIgnoreCase))
+ {
+ item.OfficialRating = result.Rated;
}
+ }
- int year;
+ int year;
- if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4
- && int.TryParse(result.Year.Substring(0, 4), NumberStyles.Number, _usCulture, out year)
- && year >= 0)
- {
- item.ProductionYear = year;
- }
+ if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4
+ && int.TryParse(result.Year.Substring(0, 4), NumberStyles.Number, _usCulture, out year)
+ && year >= 0)
+ {
+ item.ProductionYear = year;
+ }
// Seeing some bogus RT data on omdb for series, so filter it out here
// RT doesn't even have tv series
@@ -85,33 +87,33 @@ namespace MediaBrowser.Providers.Omdb
int voteCount;
- if (!string.IsNullOrEmpty(result.imdbVotes)
- && int.TryParse(result.imdbVotes, NumberStyles.Number, _usCulture, out voteCount)
- && voteCount >= 0)
- {
- item.VoteCount = voteCount;
- }
+ if (!string.IsNullOrEmpty(result.imdbVotes)
+ && int.TryParse(result.imdbVotes, NumberStyles.Number, _usCulture, out voteCount)
+ && voteCount >= 0)
+ {
+ item.VoteCount = voteCount;
+ }
- float imdbRating;
+ float imdbRating;
- if (!string.IsNullOrEmpty(result.imdbRating)
- && float.TryParse(result.imdbRating, NumberStyles.Any, _usCulture, out imdbRating)
- && imdbRating >= 0)
- {
- item.CommunityRating = imdbRating;
- }
+ if (!string.IsNullOrEmpty(result.imdbRating)
+ && float.TryParse(result.imdbRating, NumberStyles.Any, _usCulture, out imdbRating)
+ && imdbRating >= 0)
+ {
+ item.CommunityRating = imdbRating;
+ }
- if (!string.IsNullOrEmpty(result.Website))
- {
- item.HomePageUrl = result.Website;
- }
+ if (!string.IsNullOrEmpty(result.Website))
+ {
+ item.HomePageUrl = result.Website;
+ }
- if (!string.IsNullOrWhiteSpace(result.imdbID))
- {
- item.SetProviderId(MetadataProviders.Imdb, result.imdbID);
- }
+ if (!string.IsNullOrWhiteSpace(result.imdbID))
+ {
+ item.SetProviderId(MetadataProviders.Imdb, result.imdbID);
+ }
- ParseAdditionalMetadata(itemResult, result);
+ ParseAdditionalMetadata(itemResult, result);
}
public async Task<bool> FetchEpisodeData<T>(MetadataResult<T> itemResult, int episodeNumber, int seasonNumber, string imdbId, string language, string country, CancellationToken cancellationToken)
@@ -133,7 +135,7 @@ namespace MediaBrowser.Providers.Omdb
RootObject result = null;
- foreach (var episode in seasonResult.Episodes)
+ foreach (var episode in (seasonResult.Episodes ?? new RootObject[] { }))
{
if (episode.Episode == episodeNumber)
{
@@ -223,7 +225,7 @@ namespace MediaBrowser.Providers.Omdb
string resultString;
- using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 131072))
+ using (Stream stream = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
{
using (var reader = new StreamReader(stream, new UTF8Encoding(false)))
{
@@ -242,7 +244,7 @@ namespace MediaBrowser.Providers.Omdb
string resultString;
- using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 131072))
+ using (Stream stream = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
{
using (var reader = new StreamReader(stream, new UTF8Encoding(false)))
{
@@ -298,7 +300,8 @@ namespace MediaBrowser.Providers.Omdb
{
Url = url,
ResourcePool = ResourcePool,
- CancellationToken = cancellationToken
+ CancellationToken = cancellationToken,
+ BufferContent = true
}).ConfigureAwait(false))
{
@@ -338,7 +341,8 @@ namespace MediaBrowser.Providers.Omdb
{
Url = url,
ResourcePool = ResourcePool,
- CancellationToken = cancellationToken
+ CancellationToken = cancellationToken,
+ BufferContent = true
}).ConfigureAwait(false))
{
diff --git a/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs
index 93eee69ae..372813790 100644
--- a/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs
+++ b/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs
@@ -135,8 +135,7 @@ namespace MediaBrowser.Providers.People
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
index c954e6323..3645a5f8d 100644
--- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
+++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
@@ -16,7 +16,9 @@ using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
@@ -80,7 +82,7 @@ namespace MediaBrowser.Providers.People
};
result.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture));
- result.SetProviderId(MetadataProviders.Imdb, info.imdb_id.ToString(_usCulture));
+ result.SetProviderId(MetadataProviders.Imdb, info.imdb_id);
return new[] { result };
}
@@ -250,7 +252,7 @@ namespace MediaBrowser.Providers.People
{
_fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
- using (var fs = _fileSystem.GetFileStream(dataFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ using (var fs = _fileSystem.GetFileStream(dataFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await json.CopyToAsync(fs).ConfigureAwait(false);
}
@@ -406,8 +408,7 @@ namespace MediaBrowser.Providers.People
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/People/PersonMetadataService.cs b/MediaBrowser.Providers/People/PersonMetadataService.cs
index 0f8bd8b66..a306212ff 100644
--- a/MediaBrowser.Providers/People/PersonMetadataService.cs
+++ b/MediaBrowser.Providers/People/PersonMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.People
{
diff --git a/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs b/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs
index 2d4d484e6..dd3bfb4f8 100644
--- a/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs
+++ b/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs
@@ -15,6 +15,8 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.Providers.People
{
@@ -23,12 +25,16 @@ namespace MediaBrowser.Providers.People
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
private readonly IHttpClient _httpClient;
+ private readonly IFileSystem _fileSystem;
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
- public TvdbPersonImageProvider(IServerConfigurationManager config, ILibraryManager libraryManager, IHttpClient httpClient)
+ public TvdbPersonImageProvider(IServerConfigurationManager config, ILibraryManager libraryManager, IHttpClient httpClient, IFileSystem fileSystem, IXmlReaderSettingsFactory xmlSettings)
{
_config = config;
_libraryManager = libraryManager;
_httpClient = httpClient;
+ _fileSystem = fileSystem;
+ _xmlSettings = xmlSettings;
}
public string Name
@@ -56,13 +62,10 @@ namespace MediaBrowser.Providers.People
public Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
{
- // Avoid implicitly captured closure
- var itemName = item.Name;
-
var seriesWithPerson = _libraryManager.GetItemList(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Series).Name },
- Person = itemName
+ PersonIds = new[] { item.Id.ToString("N") }
}).Cast<Series>()
.Where(i => TvdbSeriesProvider.IsValidSeries(i.ProviderIds))
@@ -89,7 +92,7 @@ namespace MediaBrowser.Providers.People
{
return null;
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
return null;
}
@@ -97,46 +100,57 @@ namespace MediaBrowser.Providers.People
private RemoteImageInfo GetImageInfo(string xmlFile, string personName, CancellationToken cancellationToken)
{
- var settings = new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- };
+ var settings = _xmlSettings.Create(false);
- using (var streamReader = new StreamReader(xmlFile, Encoding.UTF8))
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
+
+ using (var fileStream = _fileSystem.GetFileStream(xmlFile, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
{
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, settings))
+ using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
{
- cancellationToken.ThrowIfCancellationRequested();
+ reader.MoveToContent();
+ reader.Read();
- if (reader.NodeType == XmlNodeType.Element)
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- switch (reader.Name)
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
{
- case "Actor":
- {
- using (var subtree = reader.ReadSubtree())
+ switch (reader.Name)
+ {
+ case "Actor":
{
- var info = FetchImageInfoFromActorNode(personName, subtree);
-
- if (info != null)
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subtree = reader.ReadSubtree())
{
- return info;
+ var info = FetchImageInfoFromActorNode(personName, subtree);
+
+ if (info != null)
+ {
+ return info;
+ }
}
+ break;
}
+ default:
+ reader.Skip();
break;
- }
- default:
- reader.Skip();
- break;
+ }
+ }
+ else
+ {
+ reader.Read();
}
}
}
@@ -154,12 +168,14 @@ namespace MediaBrowser.Providers.People
/// <returns>System.String.</returns>
private RemoteImageInfo FetchImageInfoFromActorNode(string personName, XmlReader reader)
{
- reader.MoveToContent();
-
string name = null;
string image = null;
- while (reader.Read())
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
@@ -182,6 +198,10 @@ namespace MediaBrowser.Providers.People
break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(image) &&
@@ -209,8 +229,7 @@ namespace MediaBrowser.Providers.People
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs b/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs
index 9bfff6b84..b64b2f24e 100644
--- a/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs
+++ b/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Photos
{
diff --git a/MediaBrowser.Providers/Photos/PhotoHelper.cs b/MediaBrowser.Providers/Photos/PhotoHelper.cs
deleted file mode 100644
index 2334c792e..000000000
--- a/MediaBrowser.Providers/Photos/PhotoHelper.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-using System;
-using System.Text;
-
-namespace MediaBrowser.Providers.Photos
-{
- public static class PhotoHelper
- {
- public static string Dec2Frac(double dbl)
- {
- char neg = ' ';
- double dblDecimal = dbl;
- if (dblDecimal == (int)dblDecimal) return dblDecimal.ToString(); //return no if it's not a decimal
- if (dblDecimal < 0)
- {
- dblDecimal = Math.Abs(dblDecimal);
- neg = '-';
- }
- var whole = (int)Math.Truncate(dblDecimal);
- string decpart = dblDecimal.ToString().Replace(Math.Truncate(dblDecimal) + ".", "");
- double rN = Convert.ToDouble(decpart);
- double rD = Math.Pow(10, decpart.Length);
-
- string rd = Recur(decpart);
- int rel = Convert.ToInt32(rd);
- if (rel != 0)
- {
- rN = rel;
- rD = (int)Math.Pow(10, rd.Length) - 1;
- }
- //just a few prime factors for testing purposes
- var primes = new[] { 47, 43, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2 };
- foreach (int i in primes) ReduceNo(i, ref rD, ref rN);
-
- rN = rN + (whole * rD);
- return string.Format("{0}{1}/{2}", neg, rN, rD);
- }
-
- /// <summary>
- /// Finds out the recurring decimal in a specified number
- /// </summary>
- /// <param name="db">Number to check</param>
- /// <returns></returns>
- private static string Recur(string db)
- {
- if (db.Length < 13) return "0";
- var sb = new StringBuilder();
- for (int i = 0; i < 7; i++)
- {
- sb.Append(db[i]);
- int dlength = (db.Length / sb.ToString().Length);
- int occur = Occurence(sb.ToString(), db);
- if (dlength == occur || dlength == occur - sb.ToString().Length)
- {
- return sb.ToString();
- }
- }
- return "0";
- }
-
- /// <summary>
- /// Checks for number of occurence of specified no in a number
- /// </summary>
- /// <param name="s">The no to check occurence times</param>
- /// <param name="check">The number where to check this</param>
- /// <returns></returns>
- private static int Occurence(string s, string check)
- {
- int i = 0;
- int d = s.Length;
- string ds = check;
- for (int n = (ds.Length / d); n > 0; n--)
- {
- if (ds.Contains(s))
- {
- i++;
- ds = ds.Remove(ds.IndexOf(s, System.StringComparison.Ordinal), d);
- }
- }
- return i;
- }
-
- /// <summary>
- /// Reduces a fraction given the numerator and denominator
- /// </summary>
- /// <param name="i">Number to use in an attempt to reduce fraction</param>
- /// <param name="rD">the Denominator</param>
- /// <param name="rN">the Numerator</param>
- private static void ReduceNo(int i, ref double rD, ref double rN)
- {
- //keep reducing until divisibility ends
- while ((rD % i) < 1e-10 && (rN % i) < 1e-10)
- {
- rN = rN / i;
- rD = rD / i;
- }
- }
- }
-}
diff --git a/MediaBrowser.Providers/Photos/PhotoMetadataService.cs b/MediaBrowser.Providers/Photos/PhotoMetadataService.cs
index fb6ff6f09..617a510b8 100644
--- a/MediaBrowser.Providers/Photos/PhotoMetadataService.cs
+++ b/MediaBrowser.Providers/Photos/PhotoMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Photos
{
diff --git a/MediaBrowser.Providers/Photos/PhotoProvider.cs b/MediaBrowser.Providers/Photos/PhotoProvider.cs
deleted file mode 100644
index c48c3d09b..000000000
--- a/MediaBrowser.Providers/Photos/PhotoProvider.cs
+++ /dev/null
@@ -1,169 +0,0 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using TagLib;
-using TagLib.IFD;
-using TagLib.IFD.Entries;
-using TagLib.IFD.Tags;
-
-namespace MediaBrowser.Providers.Photos
-{
- public class PhotoProvider : ICustomMetadataProvider<Photo>, IHasItemChangeMonitor, IForcedProvider
- {
- private readonly ILogger _logger;
-
- public PhotoProvider(ILogger logger)
- {
- _logger = logger;
- }
-
- public Task<ItemUpdateType> FetchAsync(Photo item, MetadataRefreshOptions options, CancellationToken cancellationToken)
- {
- item.SetImagePath(ImageType.Primary, item.Path);
-
- // Examples: https://github.com/mono/taglib-sharp/blob/a5f6949a53d09ce63ee7495580d6802921a21f14/tests/fixtures/TagLib.Tests.Images/NullOrientationTest.cs
-
- try
- {
- using (var file = TagLib.File.Create(item.Path))
- {
- var image = file as TagLib.Image.File;
-
- var tag = file.GetTag(TagTypes.TiffIFD) as IFDTag;
-
- if (tag != null)
- {
- var structure = tag.Structure;
-
- if (structure != null)
- {
- var exif = structure.GetEntry(0, (ushort)IFDEntryTag.ExifIFD) as SubIFDEntry;
-
- if (exif != null)
- {
- var exifStructure = exif.Structure;
-
- if (exifStructure != null)
- {
- var entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ApertureValue) as RationalIFDEntry;
-
- if (entry != null)
- {
- double val = entry.Value.Numerator;
- val /= entry.Value.Denominator;
- item.Aperture = val;
- }
-
- entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ShutterSpeedValue) as RationalIFDEntry;
-
- if (entry != null)
- {
- double val = entry.Value.Numerator;
- val /= entry.Value.Denominator;
- item.ShutterSpeed = val;
- }
- }
- }
- }
- }
-
- item.CameraMake = image.ImageTag.Make;
- item.CameraModel = image.ImageTag.Model;
-
- item.Width = image.Properties.PhotoWidth;
- item.Height = image.Properties.PhotoHeight;
-
- var rating = image.ImageTag.Rating;
- if (rating.HasValue)
- {
- item.CommunityRating = rating;
- }
- else
- {
- item.CommunityRating = null;
- }
-
- item.Overview = image.ImageTag.Comment;
-
- if (!string.IsNullOrWhiteSpace(image.ImageTag.Title))
- {
- item.Name = image.ImageTag.Title;
- }
-
- var dateTaken = image.ImageTag.DateTime;
- if (dateTaken.HasValue)
- {
- item.DateCreated = dateTaken.Value;
- item.PremiereDate = dateTaken.Value;
- item.ProductionYear = dateTaken.Value.Year;
- }
-
- item.Genres = image.ImageTag.Genres.ToList();
- item.Tags = image.ImageTag.Keywords.ToList();
- item.Software = image.ImageTag.Software;
-
- if (image.ImageTag.Orientation == TagLib.Image.ImageOrientation.None)
- {
- item.Orientation = null;
- }
- else
- {
- Model.Drawing.ImageOrientation orientation;
- if (Enum.TryParse(image.ImageTag.Orientation.ToString(), true, out orientation))
- {
- item.Orientation = orientation;
- }
- }
-
- item.ExposureTime = image.ImageTag.ExposureTime;
- item.FocalLength = image.ImageTag.FocalLength;
-
- item.Latitude = image.ImageTag.Latitude;
- item.Longitude = image.ImageTag.Longitude;
- item.Altitude = image.ImageTag.Altitude;
-
- if (image.ImageTag.ISOSpeedRatings.HasValue)
- {
- item.IsoSpeedRating = Convert.ToInt32(image.ImageTag.ISOSpeedRatings.Value);
- }
- else
- {
- item.IsoSpeedRating = null;
- }
- }
- }
- catch (Exception e)
- {
- _logger.ErrorException("Image Provider - Error reading image tag for {0}", e, item.Path);
- }
-
- const ItemUpdateType result = ItemUpdateType.ImageUpdate | ItemUpdateType.MetadataImport;
- return Task.FromResult(result);
- }
-
- public string Name
- {
- get { return "Embedded Information"; }
- }
-
- public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
- {
- if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path) && item.LocationType == LocationType.FileSystem)
- {
- var file = directoryService.GetFile(item.Path);
- if (file != null && file.LastWriteTimeUtc != item.DateModified)
- {
- return true;
- }
- }
-
- return false;
- }
- }
-}
diff --git a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs
index d1d5ba7de..cfdba0fb2 100644
--- a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs
+++ b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Playlists
{
diff --git a/MediaBrowser.Providers/Studios/StudioMetadataService.cs b/MediaBrowser.Providers/Studios/StudioMetadataService.cs
index 9ee594a66..c773b7896 100644
--- a/MediaBrowser.Providers/Studios/StudioMetadataService.cs
+++ b/MediaBrowser.Providers/Studios/StudioMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Studios
{
diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs
index bfb7eb8fd..bf017d148 100644
--- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs
+++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs
@@ -11,7 +11,9 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Studios
{
@@ -88,7 +90,7 @@ namespace MediaBrowser.Providers.Studios
private RemoteImageInfo GetImage(IHasImages item, string filename, ImageType type, string remoteFilename)
{
- var list = ImageUtils.GetAvailableImages(filename);
+ var list = ImageUtils.GetAvailableImages(filename, _fileSystem);
var match = ImageUtils.FindMatch(item, list);
diff --git a/MediaBrowser.Providers/Subtitles/ConfigurationExtension.cs b/MediaBrowser.Providers/Subtitles/ConfigurationExtension.cs
deleted file mode 100644
index f520915d8..000000000
--- a/MediaBrowser.Providers/Subtitles/ConfigurationExtension.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Model.Providers;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Providers.Subtitles
-{
- public static class ConfigurationExtension
- {
- public static SubtitleOptions GetSubtitleConfiguration(this IConfigurationManager manager)
- {
- return manager.GetConfiguration<SubtitleOptions>("subtitles");
- }
- }
-
- public class SubtitleConfigurationFactory : IConfigurationFactory
- {
- public IEnumerable<ConfigurationStore> GetConfigurations()
- {
- return new List<ConfigurationStore>
- {
- new ConfigurationStore
- {
- Key = "subtitles",
- ConfigurationType = typeof (SubtitleOptions)
- }
- };
- }
- }
-}
diff --git a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs
deleted file mode 100644
index 271f8170f..000000000
--- a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs
+++ /dev/null
@@ -1,340 +0,0 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Controller.Security;
-using MediaBrowser.Controller.Subtitles;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
-using OpenSubtitlesHandler;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Providers.Subtitles
-{
- public class OpenSubtitleDownloader : ISubtitleProvider, IDisposable
- {
- private readonly ILogger _logger;
- private readonly IHttpClient _httpClient;
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
-
- private readonly IServerConfigurationManager _config;
- private readonly IEncryptionManager _encryption;
-
- private readonly IJsonSerializer _json;
-
- public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption, IJsonSerializer json)
- {
- _logger = logManager.GetLogger(GetType().Name);
- _httpClient = httpClient;
- _config = config;
- _encryption = encryption;
- _json = json;
-
- _config.NamedConfigurationUpdating += _config_NamedConfigurationUpdating;
-
- Utilities.HttpClient = httpClient;
- OpenSubtitles.SetUserAgent("mediabrowser.tv");
- }
-
- private const string PasswordHashPrefix = "h:";
- void _config_NamedConfigurationUpdating(object sender, ConfigurationUpdateEventArgs e)
- {
- if (!string.Equals(e.Key, "subtitles", StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
-
- var options = (SubtitleOptions)e.NewConfiguration;
-
- if (options != null &&
- !string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash) &&
- !options.OpenSubtitlesPasswordHash.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase))
- {
- options.OpenSubtitlesPasswordHash = EncryptPassword(options.OpenSubtitlesPasswordHash);
- }
- }
-
- private string EncryptPassword(string password)
- {
- return PasswordHashPrefix + _encryption.EncryptString(password);
- }
-
- private string DecryptPassword(string password)
- {
- if (password == null ||
- !password.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase))
- {
- return string.Empty;
- }
-
- return _encryption.DecryptString(password.Substring(2));
- }
-
- public string Name
- {
- get { return "Open Subtitles"; }
- }
-
- private SubtitleOptions GetOptions()
- {
- return _config.GetSubtitleConfiguration();
- }
-
- public IEnumerable<VideoContentType> SupportedMediaTypes
- {
- get
- {
- var options = GetOptions();
-
- if (string.IsNullOrWhiteSpace(options.OpenSubtitlesUsername) ||
- string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash))
- {
- return new VideoContentType[] { };
- }
-
- return new[] { VideoContentType.Episode, VideoContentType.Movie };
- }
- }
-
- public Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
- {
- return GetSubtitlesInternal(id, GetOptions(), cancellationToken);
- }
-
- private DateTime _lastRateLimitException;
- private async Task<SubtitleResponse> GetSubtitlesInternal(string id,
- SubtitleOptions options,
- CancellationToken cancellationToken)
- {
- if (string.IsNullOrWhiteSpace(id))
- {
- throw new ArgumentNullException("id");
- }
-
- var idParts = id.Split(new[] { '-' }, 3);
-
- var format = idParts[0];
- var language = idParts[1];
- var ossId = idParts[2];
-
- var downloadsList = new[] { int.Parse(ossId, _usCulture) };
-
- await Login(cancellationToken).ConfigureAwait(false);
-
- if ((DateTime.UtcNow - _lastRateLimitException).TotalHours < 1)
- {
- throw new ApplicationException("OpenSubtitles rate limit reached");
- }
-
- var resultDownLoad = await OpenSubtitles.DownloadSubtitlesAsync(downloadsList, cancellationToken).ConfigureAwait(false);
-
- if ((resultDownLoad.Status ?? string.Empty).IndexOf("407", StringComparison.OrdinalIgnoreCase) != -1)
- {
- _lastRateLimitException = DateTime.UtcNow;
- throw new ApplicationException("OpenSubtitles rate limit reached");
- }
-
- if (!(resultDownLoad is MethodResponseSubtitleDownload))
- {
- throw new ApplicationException("Invalid response type");
- }
-
- var results = ((MethodResponseSubtitleDownload)resultDownLoad).Results;
-
- _lastRateLimitException = DateTime.MinValue;
-
- if (results.Count == 0)
- {
- var msg = string.Format("Subtitle with Id {0} was not found. Name: {1}. Status: {2}. Message: {3}",
- ossId,
- resultDownLoad.Name ?? string.Empty,
- resultDownLoad.Status ?? string.Empty,
- resultDownLoad.Message ?? string.Empty);
-
- throw new ResourceNotFoundException(msg);
- }
-
- var data = Convert.FromBase64String(results.First().Data);
-
- return new SubtitleResponse
- {
- Format = format,
- Language = language,
-
- Stream = new MemoryStream(Utilities.Decompress(new MemoryStream(data)))
- };
- }
-
- private DateTime _lastLogin;
- private async Task Login(CancellationToken cancellationToken)
- {
- if ((DateTime.UtcNow - _lastLogin).TotalSeconds < 60)
- {
- return;
- }
-
- var options = GetOptions();
-
- var user = options.OpenSubtitlesUsername ?? string.Empty;
- var password = DecryptPassword(options.OpenSubtitlesPasswordHash);
-
- var loginResponse = await OpenSubtitles.LogInAsync(user, password, "en", cancellationToken).ConfigureAwait(false);
-
- if (!(loginResponse is MethodResponseLogIn))
- {
- throw new Exception("Authentication to OpenSubtitles failed.");
- }
-
- _lastLogin = DateTime.UtcNow;
- }
-
- public async Task<IEnumerable<NameIdPair>> GetSupportedLanguages(CancellationToken cancellationToken)
- {
- await Login(cancellationToken).ConfigureAwait(false);
-
- var result = OpenSubtitles.GetSubLanguages("en");
- if (!(result is MethodResponseGetSubLanguages))
- {
- _logger.Error("Invalid response type");
- return new List<NameIdPair>();
- }
-
- var results = ((MethodResponseGetSubLanguages)result).Languages;
-
- return results.Select(i => new NameIdPair
- {
- Name = i.LanguageName,
- Id = i.SubLanguageID
- });
- }
-
- private string NormalizeLanguage(string language)
- {
- // Problem with Greek subtitle download #1349
- if (string.Equals (language, "gre", StringComparison.OrdinalIgnoreCase)) {
-
- return "ell";
- }
-
- return language;
- }
-
- public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
- {
- var imdbIdText = request.GetProviderId(MetadataProviders.Imdb);
- long imdbId = 0;
-
- switch (request.ContentType)
- {
- case VideoContentType.Episode:
- if (!request.IndexNumber.HasValue || !request.ParentIndexNumber.HasValue || string.IsNullOrEmpty(request.SeriesName))
- {
- _logger.Debug("Episode information missing");
- return new List<RemoteSubtitleInfo>();
- }
- break;
- case VideoContentType.Movie:
- if (string.IsNullOrEmpty(request.Name))
- {
- _logger.Debug("Movie name missing");
- return new List<RemoteSubtitleInfo>();
- }
- if (string.IsNullOrWhiteSpace(imdbIdText) || !long.TryParse(imdbIdText.TrimStart('t'), NumberStyles.Any, _usCulture, out imdbId))
- {
- _logger.Debug("Imdb id missing");
- return new List<RemoteSubtitleInfo>();
- }
- break;
- }
-
- if (string.IsNullOrEmpty(request.MediaPath))
- {
- _logger.Debug("Path Missing");
- return new List<RemoteSubtitleInfo>();
- }
-
- await Login(cancellationToken).ConfigureAwait(false);
-
- var subLanguageId = NormalizeLanguage(request.Language);
- var hash = Utilities.ComputeHash(request.MediaPath);
- var fileInfo = new FileInfo(request.MediaPath);
- var movieByteSize = fileInfo.Length;
- var searchImdbId = request.ContentType == VideoContentType.Movie ? imdbId.ToString(_usCulture) : "";
- var subtitleSearchParameters = request.ContentType == VideoContentType.Episode
- ? new List<SubtitleSearchParameters> {
- new SubtitleSearchParameters(subLanguageId,
- query: request.SeriesName,
- season: request.ParentIndexNumber.Value.ToString(_usCulture),
- episode: request.IndexNumber.Value.ToString(_usCulture))
- }
- : new List<SubtitleSearchParameters> {
- new SubtitleSearchParameters(subLanguageId, imdbid: searchImdbId),
- new SubtitleSearchParameters(subLanguageId, query: request.Name, imdbid: searchImdbId)
- };
- var parms = new List<SubtitleSearchParameters> {
- new SubtitleSearchParameters( subLanguageId,
- movieHash: hash,
- movieByteSize: movieByteSize,
- imdbid: searchImdbId ),
- };
- parms.AddRange(subtitleSearchParameters);
- var result = await OpenSubtitles.SearchSubtitlesAsync(parms.ToArray(), cancellationToken).ConfigureAwait(false);
- if (!(result is MethodResponseSubtitleSearch))
- {
- _logger.Error("Invalid response type");
- return new List<RemoteSubtitleInfo>();
- }
-
- Predicate<SubtitleSearchResult> mediaFilter =
- x =>
- request.ContentType == VideoContentType.Episode
- ? !string.IsNullOrEmpty(x.SeriesSeason) && !string.IsNullOrEmpty(x.SeriesEpisode) &&
- int.Parse(x.SeriesSeason, _usCulture) == request.ParentIndexNumber &&
- int.Parse(x.SeriesEpisode, _usCulture) == request.IndexNumber
- : !string.IsNullOrEmpty(x.IDMovieImdb) && long.Parse(x.IDMovieImdb, _usCulture) == imdbId;
-
- var results = ((MethodResponseSubtitleSearch)result).Results;
-
- // Avoid implicitly captured closure
- var hasCopy = hash;
-
- return results.Where(x => x.SubBad == "0" && mediaFilter(x) && (!request.IsPerfectMatch || string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase)))
- .OrderBy(x => (string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase) ? 0 : 1))
- .ThenBy(x => Math.Abs(long.Parse(x.MovieByteSize, _usCulture) - movieByteSize))
- .ThenByDescending(x => int.Parse(x.SubDownloadsCnt, _usCulture))
- .ThenByDescending(x => double.Parse(x.SubRating, _usCulture))
- .Select(i => new RemoteSubtitleInfo
- {
- Author = i.UserNickName,
- Comment = i.SubAuthorComment,
- CommunityRating = float.Parse(i.SubRating, _usCulture),
- DownloadCount = int.Parse(i.SubDownloadsCnt, _usCulture),
- Format = i.SubFormat,
- ProviderName = Name,
- ThreeLetterISOLanguageName = i.SubLanguageID,
-
- Id = i.SubFormat + "-" + i.SubLanguageID + "-" + i.IDSubtitleFile,
-
- Name = i.SubFileName,
- DateCreated = DateTime.Parse(i.SubAddDate, _usCulture),
- IsHashMatch = i.MovieHash == hasCopy
-
- }).Where(i => !string.Equals(i.Format, "sub", StringComparison.OrdinalIgnoreCase) && !string.Equals(i.Format, "idx", StringComparison.OrdinalIgnoreCase));
- }
-
- public void Dispose()
- {
- _config.NamedConfigurationUpdating -= _config_NamedConfigurationUpdating;
- }
- }
-}
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
index a57e7d2c0..cd741bed5 100644
--- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -16,7 +16,9 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Subtitles
{
@@ -131,7 +133,7 @@ namespace MediaBrowser.Providers.Subtitles
{
//var isText = MediaStream.IsTextFormat(response.Format);
- using (var fs = _fileSystem.GetFileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ using (var fs = _fileSystem.GetFileStream(savePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await stream.CopyToAsync(fs).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs
index b74eac219..f9f247999 100644
--- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -9,7 +8,10 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.TV
{
diff --git a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
index 90a185ce0..538d96c17 100644
--- a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
+++ b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
@@ -8,7 +8,9 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.TV
{
@@ -18,40 +20,46 @@ namespace MediaBrowser.Providers.TV
{
var updateType = await base.BeforeSave(item, isFullRefresh, currentUpdateType).ConfigureAwait(false);
- if (updateType <= ItemUpdateType.None)
+ var seriesName = item.FindSeriesName();
+ if (!string.Equals(item.SeriesName, seriesName, StringComparison.Ordinal))
{
- if (!string.Equals(item.SeriesName, item.FindSeriesName(), StringComparison.Ordinal))
- {
- updateType |= ItemUpdateType.MetadataImport;
- }
+ item.SeriesName = seriesName;
+ updateType |= ItemUpdateType.MetadataImport;
}
- if (updateType <= ItemUpdateType.None)
+
+ var seriesSortName = item.FindSeriesSortName();
+ if (!string.Equals(item.SeriesSortName, seriesSortName, StringComparison.Ordinal))
{
- if (!string.Equals(item.SeriesSortName, item.FindSeriesSortName(), StringComparison.Ordinal))
- {
- updateType |= ItemUpdateType.MetadataImport;
- }
+ item.SeriesSortName = seriesSortName;
+ updateType |= ItemUpdateType.MetadataImport;
}
- if (updateType <= ItemUpdateType.None)
+
+ var seasonName = item.FindSeasonName();
+ if (!string.Equals(item.SeasonName, seasonName, StringComparison.Ordinal))
{
- if (!string.Equals(item.SeasonName, item.FindSeasonName(), StringComparison.Ordinal))
- {
- updateType |= ItemUpdateType.MetadataImport;
- }
+ item.SeasonName = seasonName;
+ updateType |= ItemUpdateType.MetadataImport;
}
- if (updateType <= ItemUpdateType.None)
+
+ var seriesId = item.FindSeriesId();
+ if (item.SeriesId != seriesId)
{
- if (item.SeriesId != item.FindSeriesId())
- {
- updateType |= ItemUpdateType.MetadataImport;
- }
+ item.SeriesId = seriesId;
+ updateType |= ItemUpdateType.MetadataImport;
}
- if (updateType <= ItemUpdateType.None)
+
+ var seasonId = item.FindSeasonId();
+ if (item.SeasonId != seasonId)
+ {
+ item.SeasonId = seasonId;
+ updateType |= ItemUpdateType.MetadataImport;
+ }
+
+ var seriesPresentationUniqueKey = item.FindSeriesPresentationUniqueKey();
+ if (!string.Equals(item.SeriesPresentationUniqueKey, seriesPresentationUniqueKey, StringComparison.Ordinal))
{
- if (item.SeasonId != item.FindSeasonId())
- {
- updateType |= ItemUpdateType.MetadataImport;
- }
+ item.SeriesPresentationUniqueKey = seriesPresentationUniqueKey;
+ updateType |= ItemUpdateType.MetadataImport;
}
return updateType;
diff --git a/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs
index e6a47d9d2..884fa297f 100644
--- a/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs
@@ -18,7 +18,9 @@ using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.TV
{
@@ -101,7 +103,7 @@ namespace MediaBrowser.Providers.TV
{
// No biggie. Don't blow up
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
// No biggie. Don't blow up
}
@@ -222,8 +224,7 @@ namespace MediaBrowser.Providers.TV
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs
index 827a3c50f..8db3eaa79 100644
--- a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs
@@ -20,7 +20,9 @@ using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.TV
{
@@ -108,7 +110,7 @@ namespace MediaBrowser.Providers.TV
{
// No biggie. Don't blow up
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
// No biggie. Don't blow up
}
@@ -222,8 +224,7 @@ namespace MediaBrowser.Providers.TV
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = FanartArtistProvider.Current.FanArtResourcePool
+ Url = url
});
}
@@ -319,11 +320,12 @@ namespace MediaBrowser.Providers.TV
{
Url = url,
ResourcePool = FanartArtistProvider.Current.FanArtResourcePool,
- CancellationToken = cancellationToken
+ CancellationToken = cancellationToken,
+ BufferContent = true
}).ConfigureAwait(false))
{
- using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
await response.CopyToAsync(fileStream).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index 9c212e8a0..4992675da 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -14,11 +13,15 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Globalization;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.Providers.TV
{
- class MissingEpisodeProvider
+ public class MissingEpisodeProvider
{
private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
@@ -27,21 +30,23 @@ namespace MediaBrowser.Providers.TV
private readonly IFileSystem _fileSystem;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- private static readonly SemaphoreSlim _resourceLock = new SemaphoreSlim(1, 1);
+ private static readonly SemaphoreSlim ResourceLock = new SemaphoreSlim(1, 1);
public static bool IsRunning = false;
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
- public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, IFileSystem fileSystem)
+ public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, IFileSystem fileSystem, IXmlReaderSettingsFactory xmlSettings)
{
_logger = logger;
_config = config;
_libraryManager = libraryManager;
_localization = localization;
_fileSystem = fileSystem;
+ _xmlSettings = xmlSettings;
}
public async Task Run(List<IGrouping<string, Series>> series, bool addNewItems, CancellationToken cancellationToken)
{
- await _resourceLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+ await ResourceLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IsRunning = true;
foreach (var seriesGroup in series)
@@ -54,9 +59,10 @@ namespace MediaBrowser.Providers.TV
{
break;
}
- catch (DirectoryNotFoundException)
+ catch (IOException ex)
{
//_logger.Warn("Series files missing for series id {0}", seriesGroup.Key);
+ _logger.ErrorException("Error in missing episode provider for series id {0}", ex, seriesGroup.Key);
}
catch (Exception ex)
{
@@ -65,12 +71,15 @@ namespace MediaBrowser.Providers.TV
}
IsRunning = false;
- _resourceLock.Release();
+ ResourceLock.Release();
}
private async Task Run(IGrouping<string, Series> group, bool addNewItems, CancellationToken cancellationToken)
{
- var tvdbId = group.Key;
+ var seriesList = group.ToList();
+ var tvdbId = seriesList
+ .Select(i => i.GetProviderId(MetadataProviders.Tvdb))
+ .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
// Todo: Support series by imdb id
var seriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
@@ -78,7 +87,8 @@ namespace MediaBrowser.Providers.TV
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
- var episodeFiles = Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.TopDirectoryOnly)
+ var episodeFiles = _fileSystem.GetFilePaths(seriesDataPath)
+ .Where(i => string.Equals(Path.GetExtension(i), ".xml", StringComparison.OrdinalIgnoreCase))
.Select(Path.GetFileNameWithoutExtension)
.Where(i => i.StartsWith("episode-", StringComparison.OrdinalIgnoreCase))
.ToList();
@@ -108,30 +118,33 @@ namespace MediaBrowser.Providers.TV
.Where(i => i.Item1 != -1 && i.Item2 != -1)
.ToList();
- var hasBadData = HasInvalidContent(group);
+ var hasBadData = HasInvalidContent(seriesList);
+
+ // Be conservative here to avoid creating missing episodes for ones they already have
+ var addMissingEpisodes = !hasBadData && seriesList.All(i => _libraryManager.GetLibraryOptions(i).ImportMissingEpisodes);
- var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(group, episodeLookup)
+ var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(seriesList, episodeLookup)
.ConfigureAwait(false);
- var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(group, episodeLookup)
+ var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(seriesList, episodeLookup, addMissingEpisodes)
.ConfigureAwait(false);
var hasNewEpisodes = false;
- if (addNewItems && !group.Any(i => !i.IsInternetMetadataEnabled()))
+ if (addNewItems && seriesList.All(i => i.IsInternetMetadataEnabled()))
{
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(), hasBadData, seriesDataPath, episodeLookup, cancellationToken)
+ hasNewEpisodes = await AddMissingEpisodes(seriesList, addMissingEpisodes, seriesDataPath, episodeLookup, cancellationToken)
.ConfigureAwait(false);
}
}
if (hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved)
{
- foreach (var series in group)
+ foreach (var series in seriesList)
{
var directoryService = new DirectoryService(_logger, _fileSystem);
@@ -170,13 +183,9 @@ namespace MediaBrowser.Providers.TV
/// Adds the missing episodes.
/// </summary>
/// <param name="series">The series.</param>
- /// <param name="seriesHasBadData">if set to <c>true</c> [series has bad data].</param>
- /// <param name="seriesDataPath">The series data path.</param>
- /// <param name="episodeLookup">The episode lookup.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task<bool> AddMissingEpisodes(List<Series> series,
- bool seriesHasBadData,
+ bool addMissingEpisodes,
string seriesDataPath,
IEnumerable<Tuple<int, int>> episodeLookup,
CancellationToken cancellationToken)
@@ -223,15 +232,18 @@ namespace MediaBrowser.Providers.TV
{
continue;
}
+
var now = DateTime.UtcNow;
var targetSeries = DetermineAppropriateSeries(series, tuple.Item1);
var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(targetSeries.ProviderIds) ?? ((targetSeries.AnimeSeriesIndex ?? 1) - 1);
+ var unairedThresholdDays = 1;
+ now = now.AddDays(0 - unairedThresholdDays);
+
if (airDate.Value < now)
{
- // Be conservative here to avoid creating missing episodes for ones they already have
- if (!seriesHasBadData)
+ if (addMissingEpisodes)
{
// tvdb has a lot of nearly blank episodes
_logger.Info("Creating virtual missing episode {0} {1}x{2}", targetSeries.Name, tuple.Item1, tuple.Item2);
@@ -268,7 +280,8 @@ namespace MediaBrowser.Providers.TV
/// Removes the virtual entry after a corresponding physical version has been added
/// </summary>
private async Task<bool> RemoveObsoleteOrMissingEpisodes(IEnumerable<Series> series,
- IEnumerable<Tuple<int, int>> episodeLookup)
+ IEnumerable<Tuple<int, int>> episodeLookup,
+ bool allowMissingEpisodes)
{
var existingEpisodes = (from s in series
let seasonOffset = TvdbSeriesProvider.GetSeriesOffset(s.ProviderIds) ?? ((s.AnimeSeriesIndex ?? 1) - 1)
@@ -306,6 +319,11 @@ namespace MediaBrowser.Providers.TV
return true;
}
+ if (!allowMissingEpisodes && i.Episode.IsMissingEpisode)
+ {
+ return true;
+ }
+
return false;
}
@@ -362,7 +380,7 @@ namespace MediaBrowser.Providers.TV
var seasonNumber = i.Season.IndexNumber.Value + i.SeasonOffset;
// If there's a physical season with the same number, delete it
- if (physicalSeasons.Any(p => p.Season.IndexNumber.HasValue && (p.Season.IndexNumber.Value + p.SeasonOffset) == seasonNumber))
+ if (physicalSeasons.Any(p => p.Season.IndexNumber.HasValue && (p.Season.IndexNumber.Value + p.SeasonOffset) == seasonNumber && string.Equals(p.Season.Series.PresentationUniqueKey, i.Season.Series.PresentationUniqueKey, StringComparison.Ordinal)))
{
return true;
}
@@ -492,56 +510,65 @@ namespace MediaBrowser.Providers.TV
DateTime? airDate = null;
- // It appears the best way to filter out invalid entries is to only include those with valid air dates
- using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
+ using (var fileStream = _fileSystem.GetFileStream(xmlPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
{
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- }))
+ // It appears the best way to filter out invalid entries is to only include those with valid air dates
+ using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
+
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
{
- if (reader.NodeType == XmlNodeType.Element)
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- switch (reader.Name)
+ if (reader.NodeType == XmlNodeType.Element)
{
- case "EpisodeName":
- {
- var val = reader.ReadElementContentAsString();
- if (string.IsNullOrWhiteSpace(val))
+ switch (reader.Name)
+ {
+ case "EpisodeName":
{
- // Not valid, ignore these
- return null;
- }
- break;
- }
- case "FirstAired":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- DateTime date;
- if (DateTime.TryParse(val, out date))
+ var val = reader.ReadElementContentAsString();
+ if (string.IsNullOrWhiteSpace(val))
{
- airDate = date.ToUniversalTime();
+ // Not valid, ignore these
+ return null;
}
+ break;
}
+ case "FirstAired":
+ {
+ var val = reader.ReadElementContentAsString();
- break;
- }
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ DateTime date;
+ if (DateTime.TryParse(val, out date))
+ {
+ airDate = date.ToUniversalTime();
+ }
+ }
- default:
- reader.Skip();
- break;
+ break;
+ }
+ default:
+ {
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
}
}
}
diff --git a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs
index 78bce241f..21e327a8f 100644
--- a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs
@@ -1,4 +1,4 @@
-using CommonIO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
@@ -12,6 +12,8 @@ using MediaBrowser.Providers.Omdb;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
namespace MediaBrowser.Providers.TV
{
@@ -55,7 +57,7 @@ namespace MediaBrowser.Providers.TV
if (OmdbProvider.IsValidSeries(info.SeriesProviderIds) && info.IndexNumber.HasValue && info.ParentIndexNumber.HasValue)
{
- var seriesImdbId = info.SeriesProviderIds[MetadataProviders.Imdb.ToString()];
+ var seriesImdbId = info.GetProviderId(MetadataProviders.Imdb);
result.HasMetadata = await new OmdbProvider(_jsonSerializer, _httpClient, _fileSystem, _configurationManager).FetchEpisodeData(result, info.IndexNumber.Value, info.ParentIndexNumber.Value, seriesImdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
index cf04a1418..af7dea59e 100644
--- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
@@ -9,7 +9,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.TV
{
@@ -35,16 +37,31 @@ namespace MediaBrowser.Providers.TV
updateType |= SaveIsVirtualItem(item, episodes);
}
- if (!string.Equals(item.SeriesName, item.FindSeriesName(), StringComparison.Ordinal))
+ var seriesName = item.FindSeriesName();
+ if (!string.Equals(item.SeriesName, seriesName, StringComparison.Ordinal))
{
+ item.SeriesName = seriesName;
updateType |= ItemUpdateType.MetadataImport;
}
- if (!string.Equals(item.SeriesSortName, item.FindSeriesSortName(), StringComparison.Ordinal))
+
+ var seriesSortName = item.FindSeriesSortName();
+ if (!string.Equals(item.SeriesSortName, seriesSortName, StringComparison.Ordinal))
+ {
+ item.SeriesSortName = seriesSortName;
+ updateType |= ItemUpdateType.MetadataImport;
+ }
+
+ var seriesPresentationUniqueKey = item.FindSeriesPresentationUniqueKey();
+ if (!string.Equals(item.SeriesPresentationUniqueKey, seriesPresentationUniqueKey, StringComparison.Ordinal))
{
+ item.SeriesPresentationUniqueKey = seriesPresentationUniqueKey;
updateType |= ItemUpdateType.MetadataImport;
}
- if (item.SeriesId != item.FindSeriesId())
+
+ var seriesId = item.FindSeriesId();
+ if (item.SeriesId != seriesId)
{
+ item.SeriesId = seriesId;
updateType |= ItemUpdateType.MetadataImport;
}
diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
index f440baf5b..0d89e307f 100644
--- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -10,7 +9,10 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.TV
{
diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
deleted file mode 100644
index e038a3d28..000000000
--- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
+++ /dev/null
@@ -1,232 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using CommonIO;
-using MediaBrowser.Common.ScheduledTasks;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Plugins;
-
-namespace MediaBrowser.Providers.TV
-{
- class SeriesGroup : List<Series>, IGrouping<string, Series>
- {
- public string Key { get; set; }
- }
-
- class SeriesPostScanTask : ILibraryPostScanTask, IHasOrder
- {
- /// <summary>
- /// The _library manager
- /// </summary>
- private readonly ILibraryManager _libraryManager;
- private readonly IServerConfigurationManager _config;
- private readonly ILogger _logger;
- private readonly ILocalizationManager _localization;
- private readonly IFileSystem _fileSystem;
-
- public SeriesPostScanTask(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, ILocalizationManager localization, IFileSystem fileSystem)
- {
- _libraryManager = libraryManager;
- _logger = logger;
- _config = config;
- _localization = localization;
- _fileSystem = fileSystem;
- }
-
- public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
- {
- return RunInternal(progress, cancellationToken);
- }
-
- private Task RunInternal(IProgress<double> progress, CancellationToken cancellationToken)
- {
- var seriesList = _libraryManager.GetItemList(new InternalItemsQuery()
- {
- IncludeItemTypes = new[] { typeof(Series).Name },
- Recursive = true,
- GroupByPresentationUniqueKey = false
-
- }).Cast<Series>().ToList();
-
- var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
-
- return new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem).Run(seriesGroups, true, cancellationToken);
- }
-
- internal static IEnumerable<IGrouping<string, Series>> FindSeriesGroups(List<Series> seriesList)
- {
- var links = seriesList.ToDictionary(s => s, s => seriesList.Where(c => c != s && ShareProviderId(s, c)).ToList());
-
- var visited = new HashSet<Series>();
-
- foreach (var series in seriesList)
- {
- if (!visited.Contains(series))
- {
- var group = new SeriesGroup();
- FindAllLinked(series, visited, links, group);
-
- group.Key = group.Select(s => s.GetProviderId(MetadataProviders.Tvdb)).FirstOrDefault(id => !string.IsNullOrEmpty(id));
-
- yield return group;
- }
- }
- }
-
- private static void FindAllLinked(Series series, HashSet<Series> visited, IDictionary<Series, List<Series>> linksMap, List<Series> results)
- {
- results.Add(series);
- visited.Add(series);
-
- var links = linksMap[series];
-
- foreach (var s in links)
- {
- if (!visited.Contains(s))
- {
- FindAllLinked(s, visited, linksMap, results);
- }
- }
- }
-
- private static bool ShareProviderId(Series a, Series b)
- {
- return a.ProviderIds.Any(id =>
- {
- string value;
- return b.ProviderIds.TryGetValue(id.Key, out value) && id.Value == value;
- });
- }
-
- public int Order
- {
- get
- {
- // Run after tvdb update task
- return 1;
- }
- }
- }
-
- public class CleanMissingEpisodesEntryPoint : IServerEntryPoint
- {
- private readonly ILibraryManager _libraryManager;
- private readonly IServerConfigurationManager _config;
- private readonly ILogger _logger;
- private readonly ILocalizationManager _localization;
- private readonly IFileSystem _fileSystem;
- private readonly object _libraryChangedSyncLock = new object();
- private const int LibraryUpdateDuration = 180000;
- private readonly ITaskManager _taskManager;
-
- public CleanMissingEpisodesEntryPoint(ILibraryManager libraryManager, IServerConfigurationManager config, ILogger logger, ILocalizationManager localization, IFileSystem fileSystem, ITaskManager taskManager)
- {
- _libraryManager = libraryManager;
- _config = config;
- _logger = logger;
- _localization = localization;
- _fileSystem = fileSystem;
- _taskManager = taskManager;
- }
-
- private Timer LibraryUpdateTimer { get; set; }
-
- public void Run()
- {
- _libraryManager.ItemAdded += _libraryManager_ItemAdded;
- }
-
- private void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
- {
- if (!FilterItem(e.Item))
- {
- return;
- }
-
- lock (_libraryChangedSyncLock)
- {
- if (LibraryUpdateTimer == null)
- {
- LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite);
- }
- else
- {
- LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
- }
- }
- }
-
- private async void LibraryUpdateTimerCallback(object state)
- {
- try
- {
- if (MissingEpisodeProvider.IsRunning)
- {
- return;
- }
-
- if (_libraryManager.IsScanRunning)
- {
- return;
- }
-
- var seriesList = _libraryManager.GetItemList(new InternalItemsQuery()
- {
- IncludeItemTypes = new[] { typeof(Series).Name },
- Recursive = true,
- GroupByPresentationUniqueKey = false
-
- }).Cast<Series>().ToList();
-
- var seriesGroups = SeriesPostScanTask.FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
-
- await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem)
- .Run(seriesGroups, false, CancellationToken.None).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in SeriesPostScanTask", ex);
- }
- }
-
- private bool FilterItem(BaseItem item)
- {
- return item is Episode && item.LocationType != LocationType.Virtual;
- }
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- }
-
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources.
- /// </summary>
- /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool dispose)
- {
- if (dispose)
- {
- if (LibraryUpdateTimer != null)
- {
- LibraryUpdateTimer.Dispose();
- LibraryUpdateTimer = null;
- }
-
- _libraryManager.ItemAdded -= _libraryManager_ItemAdded;
- }
- }
- }
-}
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs
index 0feb92e89..952c4f934 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs
@@ -1,8 +1,7 @@
-using CommonIO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@@ -15,6 +14,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.TV
{
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs
index 748124c03..fcd753264 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs
@@ -1,9 +1,9 @@
-using CommonIO;
+using System;
+using MediaBrowser.Model.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -16,6 +16,9 @@ using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.TV
{
@@ -164,9 +167,24 @@ namespace MediaBrowser.Providers.TV
//and the rest from crew
if (credits.crew != null)
{
+ var keepTypes = new[] { PersonType.Director, PersonType.Writer, PersonType.Producer };
+
foreach (var person in credits.crew)
{
- result.AddPerson(new PersonInfo { Name = person.name.Trim(), Role = person.job, Type = person.department });
+ // Normalize this
+ var type = person.department;
+ if (string.Equals(type, "writing", StringComparison.OrdinalIgnoreCase))
+ {
+ type = PersonType.Writer;
+ }
+
+ if (!keepTypes.Contains(type ?? string.Empty, StringComparer.OrdinalIgnoreCase) &&
+ !keepTypes.Contains(person.job ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ result.AddPerson(new PersonInfo { Name = person.name.Trim(), Role = person.job, Type = type });
}
}
}
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs
index 821c26e4b..38831feb6 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs
@@ -1,7 +1,6 @@
-using CommonIO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
@@ -11,6 +10,9 @@ using System.Globalization;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.TV
{
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs
index 194af5b99..1f0cc9e52 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -16,7 +15,10 @@ using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.TV
{
@@ -119,8 +121,7 @@ namespace MediaBrowser.Providers.TV
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ Url = url
});
}
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs
index ad46db677..c746e0488 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs
@@ -13,6 +13,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.TV
{
@@ -20,11 +21,13 @@ namespace MediaBrowser.Providers.TV
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClient _httpClient;
+ private readonly IFileSystem _fileSystem;
- public MovieDbSeriesImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient)
+ public MovieDbSeriesImageProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem)
{
_jsonSerializer = jsonSerializer;
_httpClient = httpClient;
+ _fileSystem = fileSystem;
}
public string Name
@@ -166,7 +169,7 @@ namespace MediaBrowser.Providers.TV
if (!string.IsNullOrEmpty(path))
{
- var fileInfo = new FileInfo(path);
+ var fileInfo = _fileSystem.GetFileInfo(path);
if (fileInfo.Exists)
{
@@ -191,8 +194,7 @@ namespace MediaBrowser.Providers.TV
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs
index fb0678029..5b4ae9745 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -18,7 +17,10 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.TV
{
@@ -654,8 +656,7 @@ namespace MediaBrowser.Providers.TV
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs
index a0280cf40..791f56beb 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs
@@ -12,7 +12,9 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.TV
{
@@ -80,67 +82,73 @@ namespace MediaBrowser.Providers.TV
// Use XmlReader for best performance
using (reader)
{
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "thumb_width":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- int rval;
-
- // int.TryParse is local aware, so it can be probamatic, force us culture
- if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
- {
- width = rval;
- }
- }
- break;
- }
-
- case "thumb_height":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- int rval;
-
- // int.TryParse is local aware, so it can be probamatic, force us culture
- if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
- {
- height = rval;
- }
- }
- break;
- }
-
- case "filename":
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- url = TVUtils.BannerUrl + val;
- }
- break;
- }
-
- default:
- reader.Skip();
- break;
- }
- }
- }
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ switch (reader.Name)
+ {
+ case "thumb_width":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
+ {
+ width = rval;
+ }
+ }
+ break;
+ }
+
+ case "thumb_height":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
+ {
+ height = rval;
+ }
+ }
+ break;
+ }
+
+ case "filename":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ url = TVUtils.BannerUrl + val;
+ }
+ break;
+ }
+ default:
+ {
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
}
if (string.IsNullOrEmpty(url))
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs
index 41a2282d8..99136cd85 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs
@@ -16,7 +16,10 @@ using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.Providers.TV
{
@@ -33,13 +36,15 @@ namespace MediaBrowser.Providers.TV
private readonly IServerConfigurationManager _config;
private readonly IHttpClient _httpClient;
private readonly ILogger _logger;
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
- public TvdbEpisodeProvider(IFileSystem fileSystem, IServerConfigurationManager config, IHttpClient httpClient, ILogger logger)
+ public TvdbEpisodeProvider(IFileSystem fileSystem, IServerConfigurationManager config, IHttpClient httpClient, ILogger logger, IXmlReaderSettingsFactory xmlSettings)
{
_fileSystem = fileSystem;
_config = config;
_httpClient = httpClient;
_logger = logger;
+ _xmlSettings = xmlSettings;
Current = this;
}
@@ -47,11 +52,11 @@ namespace MediaBrowser.Providers.TV
{
var list = new List<RemoteSearchResult>();
- // The search query must either provide an episode number or date
- if (!searchInfo.IndexNumber.HasValue && !searchInfo.PremiereDate.HasValue)
- {
- return list;
- }
+ // The search query must either provide an episode number or date
+ if (!searchInfo.IndexNumber.HasValue && !searchInfo.PremiereDate.HasValue)
+ {
+ return list;
+ }
if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds))
{
@@ -59,12 +64,13 @@ namespace MediaBrowser.Providers.TV
var searchNumbers = new EpisodeNumbers();
- if (searchInfo.IndexNumber.HasValue) {
- searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
- }
-
+ if (searchInfo.IndexNumber.HasValue)
+ {
+ searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
+ }
+
searchNumbers.SeasonNumber = searchInfo.ParentIndexNumber;
- searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;
+ searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;
try
{
@@ -91,7 +97,7 @@ namespace MediaBrowser.Providers.TV
{
// Don't fail the provider because this will just keep on going and going.
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
// Don't fail the provider because this will just keep on going and going.
}
@@ -110,19 +116,20 @@ namespace MediaBrowser.Providers.TV
var result = new MetadataResult<Episode>();
result.QueriedById = true;
- if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) &&
- (searchInfo.IndexNumber.HasValue || searchInfo.PremiereDate.HasValue))
+ if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) &&
+ (searchInfo.IndexNumber.HasValue || searchInfo.PremiereDate.HasValue))
{
await TvdbSeriesProvider.Current.EnsureSeriesInfo(searchInfo.SeriesProviderIds, searchInfo.MetadataLanguage, cancellationToken).ConfigureAwait(false);
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, searchInfo.SeriesProviderIds);
var searchNumbers = new EpisodeNumbers();
- if (searchInfo.IndexNumber.HasValue) {
- searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
- }
+ if (searchInfo.IndexNumber.HasValue)
+ {
+ searchNumbers.EpisodeNumber = searchInfo.IndexNumber.Value;
+ }
searchNumbers.SeasonNumber = searchInfo.ParentIndexNumber;
- searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;
+ searchNumbers.EpisodeNumberEnd = searchInfo.IndexNumberEnd ?? searchNumbers.EpisodeNumber;
try
{
@@ -132,7 +139,7 @@ namespace MediaBrowser.Providers.TV
{
// Don't fail the provider because this will just keep on going and going.
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
// Don't fail the provider because this will just keep on going and going.
}
@@ -153,20 +160,20 @@ namespace MediaBrowser.Providers.TV
/// <returns>List{FileInfo}.</returns>
internal List<XmlReader> GetEpisodeXmlNodes(string seriesDataPath, EpisodeInfo searchInfo)
{
- var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath (searchInfo.SeriesProviderIds, searchInfo.MetadataLanguage);
-
- try
- {
- return GetXmlNodes(seriesXmlPath, searchInfo);
- }
- catch (DirectoryNotFoundException)
- {
- return new List<XmlReader> ();
- }
- catch (FileNotFoundException)
- {
- return new List<XmlReader> ();
- }
+ var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath(searchInfo.SeriesProviderIds, searchInfo.MetadataLanguage);
+
+ try
+ {
+ return GetXmlNodes(seriesXmlPath, searchInfo);
+ }
+ catch (FileNotFoundException)
+ {
+ return new List<XmlReader>();
+ }
+ catch (IOException)
+ {
+ return new List<XmlReader>();
+ }
}
private class EpisodeNumbers
@@ -186,59 +193,62 @@ namespace MediaBrowser.Providers.TV
/// <returns>Task{System.Boolean}.</returns>
private MetadataResult<Episode> FetchEpisodeData(EpisodeInfo id, EpisodeNumbers searchNumbers, string seriesDataPath, CancellationToken cancellationToken)
{
- var result = new MetadataResult<Episode>()
- {
- Item = new Episode
- {
- IndexNumber = id.IndexNumber,
- ParentIndexNumber = id.ParentIndexNumber,
- IndexNumberEnd = id.IndexNumberEnd
- }
- };
+ var result = new MetadataResult<Episode>()
+ {
+ Item = new Episode
+ {
+ IndexNumber = id.IndexNumber,
+ ParentIndexNumber = id.ParentIndexNumber,
+ IndexNumberEnd = id.IndexNumberEnd
+ }
+ };
- var xmlNodes = GetEpisodeXmlNodes (seriesDataPath, id);
+ var xmlNodes = GetEpisodeXmlNodes(seriesDataPath, id);
- if (xmlNodes.Count > 0) {
- FetchMainEpisodeInfo(result, xmlNodes[0], cancellationToken);
+ if (xmlNodes.Count > 0)
+ {
+ FetchMainEpisodeInfo(result, xmlNodes[0], cancellationToken);
- result.HasMetadata = true;
- }
+ result.HasMetadata = true;
+ }
- foreach (var node in xmlNodes.Skip(1)) {
- FetchAdditionalPartInfo(result, node, cancellationToken);
- }
+ foreach (var node in xmlNodes.Skip(1))
+ {
+ FetchAdditionalPartInfo(result, node, cancellationToken);
+ }
return result;
}
- private List<XmlReader> GetXmlNodes(string xmlFile, EpisodeInfo searchInfo)
- {
- var list = new List<XmlReader> ();
+ private List<XmlReader> GetXmlNodes(string xmlFile, EpisodeInfo searchInfo)
+ {
+ var list = new List<XmlReader>();
- if (searchInfo.IndexNumber.HasValue)
- {
- var files = GetEpisodeXmlFiles (searchInfo.ParentIndexNumber, searchInfo.IndexNumber, searchInfo.IndexNumberEnd, Path.GetDirectoryName (xmlFile));
+ if (searchInfo.IndexNumber.HasValue)
+ {
+ var files = GetEpisodeXmlFiles(searchInfo.ParentIndexNumber, searchInfo.IndexNumber, searchInfo.IndexNumberEnd, Path.GetDirectoryName(xmlFile));
- list = files.Select (GetXmlReader).ToList ();
- }
+ list = files.Select(GetXmlReader).ToList();
+ }
- if (list.Count == 0 && searchInfo.PremiereDate.HasValue) {
- list = GetXmlNodesByPremiereDate (xmlFile, searchInfo.PremiereDate.Value);
- }
+ if (list.Count == 0 && searchInfo.PremiereDate.HasValue)
+ {
+ list = GetXmlNodesByPremiereDate(xmlFile, searchInfo.PremiereDate.Value);
+ }
- return list;
- }
+ return list;
+ }
- private List<FileSystemMetadata> GetEpisodeXmlFiles(int? seasonNumber, int? episodeNumber, int? endingEpisodeNumber, string seriesDataPath)
- {
- var files = new List<FileSystemMetadata>();
+ private List<FileSystemMetadata> GetEpisodeXmlFiles(int? seasonNumber, int? episodeNumber, int? endingEpisodeNumber, string seriesDataPath)
+ {
+ var files = new List<FileSystemMetadata>();
- if (episodeNumber == null)
- {
- return files;
- }
+ if (episodeNumber == null)
+ {
+ return files;
+ }
- var usingAbsoluteData = false;
+ var usingAbsoluteData = false;
if (seasonNumber.HasValue)
{
@@ -261,230 +271,292 @@ namespace MediaBrowser.Providers.TV
}
}
- var end = endingEpisodeNumber ?? episodeNumber;
- episodeNumber++;
+ var end = endingEpisodeNumber ?? episodeNumber;
+ episodeNumber++;
- while (episodeNumber <= end)
- {
+ while (episodeNumber <= end)
+ {
string file;
- if (usingAbsoluteData)
- {
- file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
- }
- else
- {
- file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
- }
-
- var fileInfo = _fileSystem.GetFileInfo(file);
- if (fileInfo.Exists)
- {
- files.Add(fileInfo);
- }
- else
- {
- break;
- }
-
- episodeNumber++;
- }
-
- return files;
- }
-
- private XmlReader GetXmlReader(FileSystemMetadata xmlFile)
- {
- return GetXmlReader (_fileSystem.ReadAllText(xmlFile.FullName, Encoding.UTF8));
- }
-
- private XmlReader GetXmlReader(String xml)
- {
- var streamReader = new StringReader (xml);
-
- return XmlReader.Create (streamReader, new XmlReaderSettings {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- });
- }
-
- private List<XmlReader> GetXmlNodesByPremiereDate(string xmlFile, DateTime premiereDate)
- {
- var list = new List<XmlReader> ();
-
- using (var streamReader = new StreamReader (xmlFile, Encoding.UTF8)) {
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create (streamReader, new XmlReaderSettings {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- }))
- {
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "Episode":
- {
- var outerXml = reader.ReadOuterXml();
-
- var airDate = GetEpisodeAirDate (outerXml);
-
- if (airDate.HasValue && premiereDate.Date == airDate.Value.Date)
- {
- list.Add (GetXmlReader(outerXml));
- return list;
- }
-
- break;
- }
-
- default:
- reader.Skip();
- break;
- }
- }
- }
- }
- }
-
- return list;
- }
-
- private DateTime? GetEpisodeAirDate(string xml)
- {
- using (var streamReader = new StringReader (xml))
- {
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create (streamReader, new XmlReaderSettings {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- }))
- {
- reader.MoveToContent ();
-
- // Loop through each element
- while (reader.Read ()) {
-
- if (reader.NodeType == XmlNodeType.Element) {
- switch (reader.Name) {
-
- case "FirstAired":
- {
- var val = reader.ReadElementContentAsString ();
-
- if (!string.IsNullOrWhiteSpace (val)) {
- DateTime date;
- if (DateTime.TryParse (val, out date)) {
- date = date.ToUniversalTime ();
-
- return date;
- }
- }
-
- break;
- }
-
- default:
- reader.Skip ();
- break;
- }
- }
- }
- }
- }
- return null;
- }
+ if (usingAbsoluteData)
+ {
+ file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", episodeNumber));
+ }
+ else
+ {
+ file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber.Value, episodeNumber));
+ }
+
+ var fileInfo = _fileSystem.GetFileInfo(file);
+ if (fileInfo.Exists)
+ {
+ files.Add(fileInfo);
+ }
+ else
+ {
+ break;
+ }
+
+ episodeNumber++;
+ }
+
+ return files;
+ }
+
+ private XmlReader GetXmlReader(FileSystemMetadata xmlFile)
+ {
+ return GetXmlReader(_fileSystem.ReadAllText(xmlFile.FullName, Encoding.UTF8));
+ }
+
+ private XmlReader GetXmlReader(String xml)
+ {
+ var streamReader = new StringReader(xml);
+
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
+
+ return XmlReader.Create(streamReader, settings);
+ }
+
+ private List<XmlReader> GetXmlNodesByPremiereDate(string xmlFile, DateTime premiereDate)
+ {
+ var list = new List<XmlReader>();
+
+ using (var fileStream = _fileSystem.GetFileStream(xmlFile, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
+ {
+ using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
+ {
+ // Use XmlReader for best performance
+
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
+
+ using (var reader = XmlReader.Create(streamReader, settings))
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Episode":
+ {
+ var outerXml = reader.ReadOuterXml();
+
+ var airDate = GetEpisodeAirDate(outerXml);
+
+ if (airDate.HasValue && premiereDate.Date == airDate.Value.Date)
+ {
+ list.Add(GetXmlReader(outerXml));
+ return list;
+ }
+
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+ }
+ }
+
+ return list;
+ }
+
+ private DateTime? GetEpisodeAirDate(string xml)
+ {
+ using (var streamReader = new StringReader(xml))
+ {
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
+
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "FirstAired":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ DateTime date;
+ if (DateTime.TryParse(val, out date))
+ {
+ date = date.ToUniversalTime();
+
+ return date;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+ }
+ return null;
+ }
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- private void FetchMainEpisodeInfo(MetadataResult<Episode> result, XmlReader reader, CancellationToken cancellationToken)
+ private void FetchMainEpisodeInfo(MetadataResult<Episode> result, XmlReader reader, CancellationToken cancellationToken)
{
var item = result.Item;
- // Use XmlReader for best performance
- using (reader)
- {
- reader.MoveToContent();
-
- result.ResetPeople();
-
- // Loop through each element
- while (reader.Read())
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "id":
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.SetProviderId(MetadataProviders.Tvdb, val);
- }
- break;
- }
-
- case "IMDB_ID":
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.SetProviderId(MetadataProviders.Imdb, val);
- }
- 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();
+ // Use XmlReader for best performance
+ using (reader)
+ {
+ result.ResetPeople();
+
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
- if (!string.IsNullOrWhiteSpace(val))
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "id":
{
- float num;
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.SetProviderId(MetadataProviders.Tvdb, val);
+ }
+ break;
+ }
- if (float.TryParse(val, NumberStyles.Any, _usCulture, out num))
+ case "IMDB_ID":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
{
- item.DvdSeasonNumber = Convert.ToInt32(num);
+ item.SetProviderId(MetadataProviders.Imdb, val);
}
+ break;
}
- break;
- }
+ case "DVD_episodenumber":
+ {
+ var val = reader.ReadElementContentAsString();
- case "EpisodeNumber":
- {
- if (!item.IndexNumber.HasValue)
+ 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 "EpisodeNumber":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!item.IndexNumber.HasValue)
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
+ {
+ item.IndexNumber = rval;
+ }
+ }
+ }
+
+ break;
+ }
+
+ case "SeasonNumber":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!item.ParentIndexNumber.HasValue)
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
+ {
+ item.ParentIndexNumber = rval;
+ }
+ }
+ }
+
+ break;
+ }
+
+ case "absolute_number":
{
var val = reader.ReadElementContentAsString();
@@ -495,17 +567,32 @@ namespace MediaBrowser.Providers.TV
// int.TryParse is local aware, so it can be probamatic, force us culture
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
{
- item.IndexNumber = rval;
+ item.AbsoluteEpisodeNumber = rval;
}
}
+
+ break;
}
- break;
- }
+ case "airsbefore_episode":
+ {
+ var val = reader.ReadElementContentAsString();
- case "SeasonNumber":
- {
- if (!item.ParentIndexNumber.HasValue)
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
+ {
+ item.AirsBeforeEpisodeNumber = rval;
+ }
+ }
+
+ break;
+ }
+
+ case "airsafter_season":
{
var val = reader.ReadElementContentAsString();
@@ -516,225 +603,174 @@ namespace MediaBrowser.Providers.TV
// int.TryParse is local aware, so it can be probamatic, force us culture
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
{
- item.ParentIndexNumber = rval;
+ item.AirsAfterSeasonNumber = rval;
}
}
+
+ break;
}
- break;
- }
+ case "airsbefore_season":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
+ {
+ item.AirsBeforeSeasonNumber = rval;
+ }
+ }
+
+ break;
+ }
+
+ case "EpisodeName":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!item.LockedFields.Contains(MetadataFields.Name))
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Name = val;
+ }
+ }
+ break;
+ }
+
+ case "Overview":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!item.LockedFields.Contains(MetadataFields.Overview))
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Overview = val;
+ }
+ }
+ break;
+ }
+ case "Rating":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ float rval;
+
+ // float.TryParse is local aware, so it can be probamatic, force us culture
+ if (float.TryParse(val, NumberStyles.AllowDecimalPoint, _usCulture, out rval))
+ {
+ item.CommunityRating = rval;
+ }
+ }
+ break;
+ }
+ case "RatingCount":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
+ {
+ item.VoteCount = rval;
+ }
+ }
+
+ break;
+ }
+
+ case "FirstAired":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ DateTime date;
+ if (DateTime.TryParse(val, out date))
+ {
+ date = date.ToUniversalTime();
+
+ item.PremiereDate = date;
+ item.ProductionYear = date.Year;
+ }
+ }
+
+ break;
+ }
+
+ case "Director":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddPeople(result, val, PersonType.Director);
+ }
+ }
+
+ break;
+ }
+ case "GuestStars":
+ {
+ var val = reader.ReadElementContentAsString();
- case "absolute_number":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- int rval;
-
- // int.TryParse is local aware, so it can be probamatic, force us culture
- if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
- {
- item.AbsoluteEpisodeNumber = rval;
- }
- }
-
- break;
- }
-
- case "airsbefore_episode":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- int rval;
-
- // int.TryParse is local aware, so it can be probamatic, force us culture
- if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
- {
- item.AirsBeforeEpisodeNumber = rval;
- }
- }
-
- break;
- }
-
- case "airsafter_season":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- int rval;
-
- // int.TryParse is local aware, so it can be probamatic, force us culture
- if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
- {
- item.AirsAfterSeasonNumber = rval;
- }
- }
-
- break;
- }
-
- case "airsbefore_season":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- int rval;
-
- // int.TryParse is local aware, so it can be probamatic, force us culture
- if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
- {
- item.AirsBeforeSeasonNumber = rval;
- }
- }
-
- break;
- }
-
- case "EpisodeName":
- {
- if (!item.LockedFields.Contains(MetadataFields.Name))
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.Name = val;
- }
- }
- break;
- }
-
- case "Overview":
- {
- if (!item.LockedFields.Contains(MetadataFields.Overview))
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.Overview = val;
- }
- }
- break;
- }
- case "Rating":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- float rval;
-
- // float.TryParse is local aware, so it can be probamatic, force us culture
- if (float.TryParse(val, NumberStyles.AllowDecimalPoint, _usCulture, out rval))
- {
- item.CommunityRating = rval;
- }
- }
- break;
- }
- case "RatingCount":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- int rval;
-
- // int.TryParse is local aware, so it can be probamatic, force us culture
- if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
- {
- item.VoteCount = rval;
- }
- }
-
- break;
- }
-
- case "FirstAired":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- DateTime date;
- if (DateTime.TryParse(val, out date))
- {
- date = date.ToUniversalTime();
-
- item.PremiereDate = date;
- item.ProductionYear = date.Year;
- }
- }
-
- break;
- }
-
- case "Director":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddPeople(result, val, PersonType.Director);
- }
- }
-
- break;
- }
- case "GuestStars":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddGuestStars(result, val);
- }
- }
-
- break;
- }
- case "Writer":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddPeople(result, val, PersonType.Writer);
- }
- }
-
- break;
- }
- case "Language":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- result.ResultLanguage = val;
- }
-
- break;
- }
-
- default:
- reader.Skip();
- break;
- }
- }
- }
- }
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddGuestStars(result, val);
+ }
+ }
+
+ break;
+ }
+ case "Writer":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddPeople(result, val, PersonType.Writer);
+ }
+ }
+
+ break;
+ }
+ case "Language":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ result.ResultLanguage = val;
+ }
+
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
}
private void AddPeople<T>(MetadataResult<T> result, string val, string personType)
@@ -778,99 +814,104 @@ namespace MediaBrowser.Providers.TV
}
}
- private void FetchAdditionalPartInfo(MetadataResult<Episode> result, XmlReader reader, CancellationToken cancellationToken)
+ private void FetchAdditionalPartInfo(MetadataResult<Episode> result, XmlReader reader, CancellationToken cancellationToken)
{
var item = result.Item;
- // Use XmlReader for best performance
- using (reader)
- {
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "EpisodeName":
- {
- if (!item.LockedFields.Contains(MetadataFields.Name))
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.Name += ", " + val;
- }
- }
- break;
- }
-
- case "Overview":
- {
- if (!item.LockedFields.Contains(MetadataFields.Overview))
- {
- var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.Overview += Environment.NewLine + Environment.NewLine + val;
- }
- }
- break;
- }
- case "Director":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddPeople(result, val, PersonType.Director);
- }
- }
-
- break;
- }
- case "GuestStars":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddGuestStars(result, val);
- }
- }
-
- break;
- }
- case "Writer":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- if (!item.LockedFields.Contains(MetadataFields.Cast))
- {
- AddPeople(result, val, PersonType.Writer);
- }
- }
-
- break;
- }
-
- default:
- reader.Skip();
- break;
- }
- }
- }
- }
+ // Use XmlReader for best performance
+ using (reader)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "EpisodeName":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!item.LockedFields.Contains(MetadataFields.Name))
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Name += ", " + val;
+ }
+ }
+ break;
+ }
+
+ case "Overview":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!item.LockedFields.Contains(MetadataFields.Overview))
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Overview += Environment.NewLine + Environment.NewLine + val;
+ }
+ }
+ break;
+ }
+ case "Director":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddPeople(result, val, PersonType.Director);
+ }
+ }
+
+ break;
+ }
+ case "GuestStars":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddGuestStars(result, val);
+ }
+ }
+
+ break;
+ }
+ case "Writer":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ if (!item.LockedFields.Contains(MetadataFields.Cast))
+ {
+ AddPeople(result, val, PersonType.Writer);
+ }
+ }
+
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs
index d9e1037d8..8488c5669 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs
@@ -14,8 +14,11 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.Providers.TV
{
@@ -48,6 +51,7 @@ namespace MediaBrowser.Providers.TV
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
private readonly ILibraryManager _libraryManager;
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
/// <summary>
/// Initializes a new instance of the <see cref="TvdbPrescanTask"/> class.
@@ -55,13 +59,14 @@ namespace MediaBrowser.Providers.TV
/// <param name="logger">The logger.</param>
/// <param name="httpClient">The HTTP client.</param>
/// <param name="config">The config.</param>
- public TvdbPrescanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IFileSystem fileSystem, ILibraryManager libraryManager)
+ public TvdbPrescanTask(ILogger logger, IHttpClient httpClient, IServerConfigurationManager config, IFileSystem fileSystem, ILibraryManager libraryManager, IXmlReaderSettingsFactory xmlSettings)
{
_logger = logger;
_httpClient = httpClient;
_config = config;
_fileSystem = fileSystem;
_libraryManager = libraryManager;
+ _xmlSettings = xmlSettings;
}
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
@@ -101,7 +106,7 @@ namespace MediaBrowser.Providers.TV
string newUpdateTime;
- var existingDirectories = Directory.EnumerateDirectories(path)
+ var existingDirectories = _fileSystem.GetDirectoryPaths(path)
.Select(Path.GetFileName)
.ToList();
@@ -178,13 +183,11 @@ namespace MediaBrowser.Providers.TV
/// <returns>System.String.</returns>
private string GetUpdateTime(Stream response)
{
- var settings = new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- };
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
using (var streamReader = new StreamReader(response, Encoding.UTF8))
{
@@ -192,9 +195,10 @@ namespace MediaBrowser.Providers.TV
using (var reader = XmlReader.Create(streamReader, settings))
{
reader.MoveToContent();
+ reader.Read();
// Loop through each element
- while (reader.Read())
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
@@ -209,6 +213,10 @@ namespace MediaBrowser.Providers.TV
break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
}
}
@@ -251,13 +259,11 @@ namespace MediaBrowser.Providers.TV
string updateTime = null;
var idList = new List<string>();
- var settings = new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- };
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
using (var streamReader = new StreamReader(stream, Encoding.UTF8))
{
@@ -265,9 +271,10 @@ namespace MediaBrowser.Providers.TV
using (var reader = XmlReader.Create(streamReader, settings))
{
reader.MoveToContent();
+ reader.Read();
// Loop through each element
- while (reader.Read())
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
@@ -289,6 +296,10 @@ namespace MediaBrowser.Providers.TV
break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
}
}
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs
index 4b619665c..e189c292c 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs
@@ -16,7 +16,10 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.Providers.TV
{
@@ -27,12 +30,14 @@ namespace MediaBrowser.Providers.TV
private readonly IServerConfigurationManager _config;
private readonly IHttpClient _httpClient;
private readonly IFileSystem _fileSystem;
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
- public TvdbSeasonImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
+ public TvdbSeasonImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IXmlReaderSettingsFactory xmlSettings)
{
_config = config;
_httpClient = httpClient;
_fileSystem = fileSystem;
+ _xmlSettings = xmlSettings;
}
public string Name
@@ -78,13 +83,13 @@ namespace MediaBrowser.Providers.TV
try
{
- return GetImages(path, item.GetPreferredMetadataLanguage(), seasonNumber, cancellationToken);
+ return GetImages(path, item.GetPreferredMetadataLanguage(), seasonNumber, _xmlSettings, _fileSystem, cancellationToken);
}
catch (FileNotFoundException)
{
// No tvdb data yet. Don't blow up
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
// No tvdb data yet. Don't blow up
}
@@ -103,45 +108,56 @@ namespace MediaBrowser.Providers.TV
return seasonNumber;
}
- internal static IEnumerable<RemoteImageInfo> GetImages(string xmlPath, string preferredLanguage, int seasonNumber, CancellationToken cancellationToken)
+ internal static IEnumerable<RemoteImageInfo> GetImages(string xmlPath, string preferredLanguage, int seasonNumber, IXmlReaderSettingsFactory xmlReaderSettingsFactory, IFileSystem fileSystem, CancellationToken cancellationToken)
{
- var settings = new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- };
+ var settings = xmlReaderSettingsFactory.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
var list = new List<RemoteImageInfo>();
- using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
+ using (var fileStream = fileSystem.GetFileStream(xmlPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
{
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, settings))
+ using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
{
- cancellationToken.ThrowIfCancellationRequested();
+ reader.MoveToContent();
+ reader.Read();
- if (reader.NodeType == XmlNodeType.Element)
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- switch (reader.Name)
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
{
- case "Banner":
- {
- using (var subtree = reader.ReadSubtree())
+ switch (reader.Name)
+ {
+ case "Banner":
{
- AddImage(subtree, list, seasonNumber);
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subtree = reader.ReadSubtree())
+ {
+ AddImage(subtree, list, seasonNumber);
+ }
+ break;
}
+ default:
+ reader.Skip();
break;
- }
- default:
- reader.Skip();
- break;
+ }
+ }
+ else
+ {
+ reader.Read();
}
}
}
@@ -189,7 +205,11 @@ namespace MediaBrowser.Providers.TV
int? voteCount = null;
string thumbnailUrl = null;
- while (reader.Read())
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
@@ -290,6 +310,10 @@ namespace MediaBrowser.Providers.TV
break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
if (!string.IsNullOrEmpty(url) && bannerSeason.HasValue && bannerSeason.Value == seasonNumber)
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs
index c8efbfb14..2595ad585 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs
@@ -16,7 +16,10 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.Providers.TV
{
@@ -26,12 +29,14 @@ namespace MediaBrowser.Providers.TV
private readonly IHttpClient _httpClient;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IFileSystem _fileSystem;
+ private readonly IXmlReaderSettingsFactory _xmlReaderSettingsFactory;
- public TvdbSeriesImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
+ public TvdbSeriesImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, IXmlReaderSettingsFactory xmlReaderSettingsFactory)
{
_config = config;
_httpClient = httpClient;
_fileSystem = fileSystem;
+ _xmlReaderSettingsFactory = xmlReaderSettingsFactory;
}
public string Name
@@ -73,7 +78,7 @@ namespace MediaBrowser.Providers.TV
{
var seriesOffset = TvdbSeriesProvider.GetSeriesOffset(item.ProviderIds);
if (seriesOffset != null && seriesOffset.Value != 0)
- return TvdbSeasonImageProvider.GetImages(path, language, seriesOffset.Value + 1, cancellationToken);
+ return TvdbSeasonImageProvider.GetImages(path, language, seriesOffset.Value + 1, _xmlReaderSettingsFactory, _fileSystem, cancellationToken);
return GetImages(path, language, cancellationToken);
}
@@ -81,7 +86,7 @@ namespace MediaBrowser.Providers.TV
{
// No tvdb data yet. Don't blow up
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
// No tvdb data yet. Don't blow up
}
@@ -92,43 +97,54 @@ namespace MediaBrowser.Providers.TV
private IEnumerable<RemoteImageInfo> GetImages(string xmlPath, string preferredLanguage, CancellationToken cancellationToken)
{
- var settings = new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- };
+ var settings = _xmlReaderSettingsFactory.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
var list = new List<RemoteImageInfo>();
- using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
+ using (var fileStream = _fileSystem.GetFileStream(xmlPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
{
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, settings))
+ using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
{
- cancellationToken.ThrowIfCancellationRequested();
+ reader.MoveToContent();
+ reader.Read();
- if (reader.NodeType == XmlNodeType.Element)
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- switch (reader.Name)
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
{
- case "Banner":
- {
- using (var subtree = reader.ReadSubtree())
+ switch (reader.Name)
+ {
+ case "Banner":
{
- AddImage(subtree, list);
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subtree = reader.ReadSubtree())
+ {
+ AddImage(subtree, list);
+ }
+ break;
}
+ default:
+ reader.Skip();
break;
- }
- default:
- reader.Skip();
- break;
+ }
+ }
+ else
+ {
+ reader.Read();
}
}
}
@@ -175,7 +191,11 @@ namespace MediaBrowser.Providers.TV
int? voteCount = null;
string thumbnailUrl = null;
- while (reader.Read())
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
@@ -277,6 +297,10 @@ namespace MediaBrowser.Providers.TV
break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
if (!string.IsNullOrEmpty(url) && !bannerSeason.HasValue)
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
index 2572a4f58..cc8a90fe3 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
@@ -20,8 +20,8 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
-using CommonIO;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Model.Globalization;
+using MediaBrowser.Model.Xml;
namespace MediaBrowser.Providers.TV
{
@@ -35,13 +35,15 @@ namespace MediaBrowser.Providers.TV
private readonly IZipClient _zipClient;
private readonly IHttpClient _httpClient;
private readonly IFileSystem _fileSystem;
+ private readonly IXmlReaderSettingsFactory _xmlSettings;
private readonly IServerConfigurationManager _config;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager;
- private readonly IMemoryStreamProvider _memoryStreamProvider;
+ private readonly IMemoryStreamFactory _memoryStreamProvider;
+ private readonly ILocalizationManager _localizationManager;
- public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IMemoryStreamProvider memoryStreamProvider)
+ public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ILibraryManager libraryManager, IMemoryStreamFactory memoryStreamProvider, IXmlReaderSettingsFactory xmlSettings, ILocalizationManager localizationManager)
{
_zipClient = zipClient;
_httpClient = httpClient;
@@ -50,6 +52,8 @@ namespace MediaBrowser.Providers.TV
_logger = logger;
_libraryManager = libraryManager;
_memoryStreamProvider = memoryStreamProvider;
+ _xmlSettings = xmlSettings;
+ _localizationManager = localizationManager;
Current = this;
}
@@ -251,7 +255,8 @@ namespace MediaBrowser.Providers.TV
}
// Sanitize all files, except for extracted episode files
- foreach (var file in Directory.EnumerateFiles(seriesDataPath, "*.xml", SearchOption.AllDirectories).ToList()
+ foreach (var file in _fileSystem.GetFilePaths(seriesDataPath, true).ToList()
+ .Where(i => string.Equals(Path.GetExtension(i), ".xml", StringComparison.OrdinalIgnoreCase))
.Where(i => !Path.GetFileName(i).StartsWith("episode-", StringComparison.OrdinalIgnoreCase)))
{
await SanitizeXmlFile(file).ConfigureAwait(false);
@@ -280,22 +285,95 @@ namespace MediaBrowser.Providers.TV
}).ConfigureAwait(false))
{
- var doc = new XmlDocument();
- doc.Load(result);
+ return FindSeriesId(result);
+ }
+ }
+
+ private string FindSeriesId(Stream stream)
+ {
+ using (var streamReader = new StreamReader(stream, Encoding.UTF8))
+ {
+ var settings = _xmlSettings.Create(false);
- if (doc.HasChildNodes)
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
+
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
{
- var node = doc.SelectSingleNode("//Series/seriesid");
+ reader.MoveToContent();
+ reader.Read();
- if (node != null)
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- var idResult = node.InnerText;
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Series":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subtree = reader.ReadSubtree())
+ {
+ return FindSeriesId(subtree);
+ }
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
+ }
+ }
+ }
- _logger.Info("Tvdb GetSeriesByRemoteId produced id of {0}", idResult ?? string.Empty);
+ return null;
+ }
- return idResult;
+ private string FindSeriesId(XmlReader reader)
+ {
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "seriesid":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ return val;
+ }
+
+ return null;
+ }
+
+ default:
+ reader.Skip();
+ break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
return null;
@@ -304,7 +382,7 @@ namespace MediaBrowser.Providers.TV
internal static bool IsValidSeries(Dictionary<string, string> seriesProviderIds)
{
string id;
- if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id) && !string.IsNullOrEmpty(id))
+ if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out id))
{
// This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet.
if (!string.IsNullOrWhiteSpace(id))
@@ -313,7 +391,7 @@ namespace MediaBrowser.Providers.TV
}
}
- if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id) && !string.IsNullOrEmpty(id))
+ if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out id))
{
// This check should ideally never be necessary but we're seeing some cases of this and haven't tracked them down yet.
if (!string.IsNullOrWhiteSpace(id))
@@ -332,7 +410,7 @@ namespace MediaBrowser.Providers.TV
try
{
string seriesId;
- if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId) && !string.IsNullOrEmpty(seriesId))
+ if (seriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesId) && !string.IsNullOrWhiteSpace(seriesId))
{
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
@@ -346,7 +424,7 @@ namespace MediaBrowser.Providers.TV
return seriesDataPath;
}
- if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId) && !string.IsNullOrEmpty(seriesId))
+ if (seriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesId) && !string.IsNullOrWhiteSpace(seriesId))
{
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesProviderIds);
@@ -401,11 +479,11 @@ namespace MediaBrowser.Providers.TV
}
return true;
}
- catch (DirectoryNotFoundException)
+ catch (FileNotFoundException)
{
return false;
}
- catch (FileNotFoundException)
+ catch (IOException)
{
return false;
}
@@ -449,9 +527,11 @@ namespace MediaBrowser.Providers.TV
private async Task<IEnumerable<RemoteSearchResult>> FindSeriesInternal(string name, string language, CancellationToken cancellationToken)
{
var url = string.Format(SeriesSearchUrl, WebUtility.UrlEncode(name), NormalizeLanguage(language));
- var doc = new XmlDocument();
+ var searchResults = new List<RemoteSearchResult>();
- using (var results = await _httpClient.Get(new HttpRequestOptions
+ var comparableName = GetComparableName(name);
+
+ using (var stream = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
ResourcePool = TvDbResourcePool,
@@ -459,100 +539,186 @@ namespace MediaBrowser.Providers.TV
}).ConfigureAwait(false))
{
- doc.Load(results);
- }
+ var settings = _xmlSettings.Create(false);
- var searchResults = new List<RemoteSearchResult>();
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
- if (doc.HasChildNodes)
- {
- var nodes = doc.SelectNodes("//Series");
- var comparableName = GetComparableName(name);
- if (nodes != null)
+ using (var streamReader = new StreamReader(stream, Encoding.UTF8))
{
- foreach (XmlNode node in nodes)
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
{
- var searchResult = new RemoteSearchResult
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- SearchProviderName = Name
- };
+ cancellationToken.ThrowIfCancellationRequested();
- var titles = new List<string>();
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Series":
+ {
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subtree = reader.ReadSubtree())
+ {
+ var searchResult = GetSeriesSearchResultFromSubTree(subtree, comparableName);
+ if (searchResult != null)
+ {
+ searchResult.SearchProviderName = Name;
+ searchResults.Add(searchResult);
+ }
+ }
+ break;
+ }
- var nameNode = node.SelectSingleNode("./SeriesName");
- if (nameNode != null)
- {
- titles.Add(GetComparableName(nameNode.InnerText));
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
+ }
}
+ }
+ }
+ }
- var aliasNode = node.SelectSingleNode("./AliasNames");
- if (aliasNode != null)
- {
- var alias = aliasNode.InnerText.Split('|').Select(GetComparableName);
- titles.AddRange(alias);
- }
+ if (searchResults.Count == 0)
+ {
+ _logger.Info("TVDb Provider - Could not find " + name + ". Check name on Thetvdb.org.");
+ }
- var imdbIdNode = node.SelectSingleNode("./IMDB_ID");
- if (imdbIdNode != null)
- {
- var val = imdbIdNode.InnerText;
- if (!string.IsNullOrWhiteSpace(val))
+ return searchResults;
+ }
+
+ private RemoteSearchResult GetSeriesSearchResultFromSubTree(XmlReader reader, string comparableName)
+ {
+ var searchResult = new RemoteSearchResult
+ {
+ SearchProviderName = Name
+ };
+
+ var titles = new List<string>();
+ string seriesId = null;
+
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "SeriesName":
{
- searchResult.SetProviderId(MetadataProviders.Imdb, val);
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ titles.Add(GetComparableName(val));
+ }
+ break;
}
- }
- var bannerNode = node.SelectSingleNode("./banner");
- if (bannerNode != null)
- {
- var val = bannerNode.InnerText;
- if (!string.IsNullOrWhiteSpace(val))
+ case "AliasNames":
{
- searchResult.ImageUrl = TVUtils.BannerUrl + val;
+ var val = reader.ReadElementContentAsString();
+
+ var alias = (val ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(GetComparableName);
+ titles.AddRange(alias);
+ break;
}
- }
- var airDateNode = node.SelectSingleNode("./FirstAired");
- if (airDateNode != null)
- {
- var val = airDateNode.InnerText;
- if (!string.IsNullOrWhiteSpace(val))
+ case "IMDB_ID":
{
- DateTime date;
- if (DateTime.TryParse(val, out date))
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
{
- searchResult.ProductionYear = date.Year;
+ searchResult.SetProviderId(MetadataProviders.Imdb, val);
}
+ break;
}
- }
- foreach (var title in titles)
- {
- if (string.Equals(title, comparableName, StringComparison.OrdinalIgnoreCase))
+ case "banner":
{
- var id = node.SelectSingleNode("./seriesid") ??
- node.SelectSingleNode("./id");
+ var val = reader.ReadElementContentAsString();
- if (id != null)
+ if (!string.IsNullOrWhiteSpace(val))
{
- searchResult.Name = title;
- searchResult.SetProviderId(MetadataProviders.Tvdb, id.InnerText);
- searchResults.Add(searchResult);
+ searchResult.ImageUrl = TVUtils.BannerUrl + val;
}
break;
}
- _logger.Info("TVDb Provider - " + title + " did not match " + comparableName);
- }
+
+ case "FirstAired":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ DateTime date;
+ if (DateTime.TryParse(val, out date))
+ {
+ searchResult.ProductionYear = date.Year;
+ }
+ }
+ break;
+ }
+
+ case "id":
+ case "seriesid":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ seriesId = val;
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
- if (searchResults.Count == 0)
+ foreach (var title in titles)
{
- _logger.Info("TVDb Provider - Could not find " + name + ". Check name on Thetvdb.org.");
+ if (string.Equals(title, comparableName, StringComparison.OrdinalIgnoreCase))
+ {
+ if (!string.IsNullOrWhiteSpace(seriesId))
+ {
+ searchResult.Name = title;
+ searchResult.SetProviderId(MetadataProviders.Tvdb, seriesId);
+ return searchResult;
+ }
+ break;
+ }
+ _logger.Info("TVDb Provider - " + title + " did not match " + comparableName);
}
- return searchResults;
+ return null;
}
/// <summary>
@@ -569,10 +735,10 @@ namespace MediaBrowser.Providers.TV
/// </summary>
/// <param name="name">The name.</param>
/// <returns>System.String.</returns>
- internal static string GetComparableName(string name)
+ private string GetComparableName(string name)
{
name = name.ToLower();
- name = name.Normalize(NormalizationForm.FormKD);
+ name = _localizationManager.NormalizeFormKD(name);
var sb = new StringBuilder();
foreach (var c in name)
{
@@ -614,58 +780,74 @@ namespace MediaBrowser.Providers.TV
private void FetchSeriesInfo(MetadataResult<Series> result, string seriesXmlPath, CancellationToken cancellationToken)
{
- var settings = new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- };
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
var episiodeAirDates = new List<DateTime>();
- using (var streamReader = new StreamReader(seriesXmlPath, Encoding.UTF8))
+ using (var fileStream = _fileSystem.GetFileStream(seriesXmlPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
{
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, settings))
+ using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
{
- cancellationToken.ThrowIfCancellationRequested();
+ reader.MoveToContent();
+ reader.Read();
- if (reader.NodeType == XmlNodeType.Element)
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- switch (reader.Name)
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
{
- case "Series":
- {
- using (var subtree = reader.ReadSubtree())
+ switch (reader.Name)
+ {
+ case "Series":
{
- FetchDataFromSeriesNode(result, subtree, cancellationToken);
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchDataFromSeriesNode(result, subtree, cancellationToken);
+ }
+ break;
}
- break;
- }
- case "Episode":
- {
- using (var subtree = reader.ReadSubtree())
+ case "Episode":
{
- var date = GetFirstAiredDateFromEpisodeNode(subtree, cancellationToken);
-
- if (date.HasValue)
+ if (reader.IsEmptyElement)
{
- episiodeAirDates.Add(date.Value);
+ reader.Read();
+ continue;
}
+ using (var subtree = reader.ReadSubtree())
+ {
+ var date = GetFirstAiredDateFromEpisodeNode(subtree, cancellationToken);
+
+ if (date.HasValue)
+ {
+ episiodeAirDates.Add(date.Value);
+ }
+ }
+ break;
}
- break;
- }
- default:
- reader.Skip();
- break;
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
}
}
}
@@ -684,9 +866,10 @@ namespace MediaBrowser.Providers.TV
int? seasonNumber = null;
reader.MoveToContent();
+ reader.Read();
// Loop through each element
- while (reader.Read())
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -733,6 +916,10 @@ namespace MediaBrowser.Providers.TV
break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
if (seasonNumber.HasValue && seasonNumber.Value != 0)
@@ -750,39 +937,50 @@ namespace MediaBrowser.Providers.TV
/// <param name="actorsXmlPath">The actors XML path.</param>
private void FetchActors(MetadataResult<Series> result, string actorsXmlPath)
{
- var settings = new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- };
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
- using (var streamReader = new StreamReader(actorsXmlPath, Encoding.UTF8))
+ using (var fileStream = _fileSystem.GetFileStream(actorsXmlPath, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
{
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, settings))
+ using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
{
- if (reader.NodeType == XmlNodeType.Element)
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- switch (reader.Name)
+ if (reader.NodeType == XmlNodeType.Element)
{
- case "Actor":
- {
- using (var subtree = reader.ReadSubtree())
+ switch (reader.Name)
+ {
+ case "Actor":
{
- FetchDataFromActorNode(result, subtree);
+ if (reader.IsEmptyElement)
+ {
+ reader.Read();
+ continue;
+ }
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchDataFromActorNode(result, subtree);
+ }
+ break;
}
+ default:
+ reader.Skip();
break;
- }
- default:
- reader.Skip();
- break;
+ }
+ }
+ else
+ {
+ reader.Read();
}
}
}
@@ -801,7 +999,11 @@ namespace MediaBrowser.Providers.TV
var personInfo = new PersonInfo();
- while (reader.Read())
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
@@ -821,6 +1023,7 @@ namespace MediaBrowser.Providers.TV
case "id":
{
+ reader.Skip();
break;
}
@@ -856,6 +1059,10 @@ namespace MediaBrowser.Providers.TV
break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
personInfo.Type = PersonType.Actor;
@@ -871,9 +1078,10 @@ namespace MediaBrowser.Providers.TV
Series item = result.Item;
reader.MoveToContent();
+ reader.Read();
// Loop through each element
- while (reader.Read())
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -1099,6 +1307,10 @@ namespace MediaBrowser.Providers.TV
break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
}
@@ -1111,39 +1323,45 @@ namespace MediaBrowser.Providers.TV
/// <returns>Task.</returns>
private async Task ExtractEpisodes(string seriesDataPath, string xmlFile, long? lastTvDbUpdateTime)
{
- var settings = new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- };
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
- using (var streamReader = new StreamReader(xmlFile, Encoding.UTF8))
+ using (var fileStream = _fileSystem.GetFileStream(xmlFile, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read))
{
- // Use XmlReader for best performance
- using (var reader = XmlReader.Create(streamReader, settings))
+ using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
- reader.MoveToContent();
-
- // Loop through each element
- while (reader.Read())
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
{
- if (reader.NodeType == XmlNodeType.Element)
+ reader.MoveToContent();
+ reader.Read();
+
+ // Loop through each element
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
- switch (reader.Name)
+ if (reader.NodeType == XmlNodeType.Element)
{
- case "Episode":
- {
- var outerXml = reader.ReadOuterXml();
+ switch (reader.Name)
+ {
+ case "Episode":
+ {
+ var outerXml = reader.ReadOuterXml();
- await SaveEpsiodeXml(seriesDataPath, outerXml, lastTvDbUpdateTime).ConfigureAwait(false);
- break;
- }
+ await SaveEpsiodeXml(seriesDataPath, outerXml, lastTvDbUpdateTime).ConfigureAwait(false);
+ break;
+ }
- default:
- reader.Skip();
- break;
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ else
+ {
+ reader.Read();
}
}
}
@@ -1153,13 +1371,11 @@ namespace MediaBrowser.Providers.TV
private async Task SaveEpsiodeXml(string seriesDataPath, string xml, long? lastTvDbUpdateTime)
{
- var settings = new XmlReaderSettings
- {
- CheckCharacters = false,
- IgnoreProcessingInstructions = true,
- IgnoreComments = true,
- ValidationType = ValidationType.None
- };
+ var settings = _xmlSettings.Create(false);
+
+ settings.CheckCharacters = false;
+ settings.IgnoreProcessingInstructions = true;
+ settings.IgnoreComments = true;
var seasonNumber = -1;
var episodeNumber = -1;
@@ -1172,9 +1388,10 @@ namespace MediaBrowser.Providers.TV
using (var reader = XmlReader.Create(streamReader, settings))
{
reader.MoveToContent();
+ reader.Read();
// Loop through each element
- while (reader.Read())
+ while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
{
@@ -1233,6 +1450,10 @@ namespace MediaBrowser.Providers.TV
break;
}
}
+ else
+ {
+ reader.Read();
+ }
}
}
}
@@ -1252,13 +1473,16 @@ namespace MediaBrowser.Providers.TV
// Only save the file if not already there, or if the episode has changed
if (hasEpisodeChanged || !_fileSystem.FileExists(file))
{
- using (var writer = XmlWriter.Create(file, new XmlWriterSettings
- {
- Encoding = Encoding.UTF8,
- Async = true
- }))
+ using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true))
{
- await writer.WriteRawAsync(xml).ConfigureAwait(false);
+ using (var writer = XmlWriter.Create(fileStream, new XmlWriterSettings
+ {
+ Encoding = Encoding.UTF8,
+ Async = true
+ }))
+ {
+ await writer.WriteRawAsync(xml).ConfigureAwait(false);
+ }
}
}
@@ -1269,13 +1493,16 @@ namespace MediaBrowser.Providers.TV
// Only save the file if not already there, or if the episode has changed
if (hasEpisodeChanged || !_fileSystem.FileExists(file))
{
- using (var writer = XmlWriter.Create(file, new XmlWriterSettings
- {
- Encoding = Encoding.UTF8,
- Async = true
- }))
+ using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.None, true))
{
- await writer.WriteRawAsync(xml).ConfigureAwait(false);
+ using (var writer = XmlWriter.Create(fileStream, new XmlWriterSettings
+ {
+ Encoding = Encoding.UTF8,
+ Async = true
+ }))
+ {
+ await writer.WriteRawAsync(xml).ConfigureAwait(false);
+ }
}
}
}
@@ -1338,7 +1565,7 @@ namespace MediaBrowser.Providers.TV
_fileSystem.DeleteFile(file);
}
}
- catch (DirectoryNotFoundException)
+ catch (IOException)
{
// No biggie
}
@@ -1353,7 +1580,7 @@ namespace MediaBrowser.Providers.TV
{
string validXml;
- using (var fileStream = _fileSystem.GetFileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, true))
+ using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true))
{
using (var reader = new StreamReader(fileStream))
{
@@ -1363,7 +1590,7 @@ namespace MediaBrowser.Providers.TV
}
}
- using (var fileStream = _fileSystem.GetFileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ using (var fileStream = _fileSystem.GetFileStream(file, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
using (var writer = new StreamWriter(fileStream))
{
diff --git a/MediaBrowser.Providers/Users/UserMetadataService.cs b/MediaBrowser.Providers/Users/UserMetadataService.cs
index 0637e9a02..274d04efd 100644
--- a/MediaBrowser.Providers/Users/UserMetadataService.cs
+++ b/MediaBrowser.Providers/Users/UserMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Users
{
diff --git a/MediaBrowser.Providers/Videos/VideoMetadataService.cs b/MediaBrowser.Providers/Videos/VideoMetadataService.cs
index a4fc462ef..49f7e11ba 100644
--- a/MediaBrowser.Providers/Videos/VideoMetadataService.cs
+++ b/MediaBrowser.Providers/Videos/VideoMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Videos
{
diff --git a/MediaBrowser.Providers/Years/YearMetadataService.cs b/MediaBrowser.Providers/Years/YearMetadataService.cs
index fd65c379d..72f8eb471 100644
--- a/MediaBrowser.Providers/Years/YearMetadataService.cs
+++ b/MediaBrowser.Providers/Years/YearMetadataService.cs
@@ -6,7 +6,9 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using CommonIO;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Years
{
diff --git a/MediaBrowser.Providers/packages.config b/MediaBrowser.Providers/packages.config
deleted file mode 100644
index da365b0ce..000000000
--- a/MediaBrowser.Providers/packages.config
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
- <package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
- <package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
- <package id="morelinq" version="1.4.0" targetFramework="net45" />
- <package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
- <package id="taglib" version="2.1.0.0" targetFramework="net45" />
-</packages> \ No newline at end of file
diff --git a/MediaBrowser.Providers/project.json b/MediaBrowser.Providers/project.json
new file mode 100644
index 000000000..fbbe9eaf3
--- /dev/null
+++ b/MediaBrowser.Providers/project.json
@@ -0,0 +1,17 @@
+{
+ "frameworks":{
+ "netstandard1.6":{
+ "dependencies":{
+ "NETStandard.Library":"1.6.0",
+ }
+ },
+ ".NETPortable,Version=v4.5,Profile=Profile7":{
+ "buildOptions": {
+ "define": [ ]
+ },
+ "frameworkAssemblies":{
+
+ }
+ }
+ }
+} \ No newline at end of file