aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BDInfo/BDROM.cs4
-rw-r--r--Emby.Common.Implementations/Devices/DeviceId.cs2
-rw-r--r--Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs2
-rw-r--r--Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs2
-rw-r--r--Emby.Common.Implementations/IO/ManagedFileSystem.cs56
-rw-r--r--Emby.Common.Implementations/IO/SharpCifsFileSystem.cs28
-rw-r--r--Emby.Common.Implementations/Net/NetAcceptSocket.cs2
-rw-r--r--Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs4
-rw-r--r--Emby.Drawing.ImageMagick/ImageMagickEncoder.cs2
-rw-r--r--Emby.Drawing.ImageMagick/PlayedIndicatorDrawer.cs6
-rw-r--r--Emby.Drawing.Net/GDIImageEncoder.cs4
-rw-r--r--Emby.Drawing/ImageProcessor.cs14
-rw-r--r--Emby.Server.Core/ApplicationHost.cs49
-rw-r--r--Emby.Server.Core/IO/LibraryMonitor.cs12
-rw-r--r--Emby.Server.Implementations/Channels/ChannelManager.cs19
-rw-r--r--Emby.Server.Implementations/Collections/CollectionManager.cs6
-rw-r--r--Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs112
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs125
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs7
-rw-r--r--Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs12
-rw-r--r--Emby.Server.Implementations/HttpServer/FileWriter.cs10
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpResultFactory.cs5
-rw-r--r--Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs11
-rw-r--r--Emby.Server.Implementations/HttpServer/ResponseFilter.cs20
-rw-r--r--Emby.Server.Implementations/IO/FileRefresher.cs2
-rw-r--r--Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs4
-rw-r--r--Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs2
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs41
-rw-r--r--Emby.Server.Implementations/Library/MusicManager.cs79
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs7
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs1
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs1
-rw-r--r--Emby.Server.Implementations/Library/SearchEngine.cs11
-rw-r--r--Emby.Server.Implementations/Library/UserManager.cs7
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs28
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs85
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs7
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs5
-rw-r--r--Emby.Server.Implementations/Logging/UnhandledExceptionWriter.cs8
-rw-r--r--Emby.Server.Implementations/MediaEncoder/EncodingManager.cs2
-rw-r--r--Emby.Server.Implementations/Playlists/PlaylistManager.cs6
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs2
-rw-r--r--Emby.Server.Implementations/Security/MBLicenseFile.cs2
-rw-r--r--Emby.Server.Implementations/Session/HttpSessionController.cs2
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs3
-rw-r--r--Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs2
-rw-r--r--Emby.Server.Implementations/Updates/InstallationManager.cs4
-rw-r--r--MediaBrowser.Api/ApiEntryPoint.cs2
-rw-r--r--MediaBrowser.Api/BaseApiService.cs4
-rw-r--r--MediaBrowser.Api/ChannelService.cs4
-rw-r--r--MediaBrowser.Api/EnvironmentService.cs2
-rw-r--r--MediaBrowser.Api/Images/ImageByNameService.cs2
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs4
-rw-r--r--MediaBrowser.Api/Images/RemoteImageService.cs4
-rw-r--r--MediaBrowser.Api/ItemLookupService.cs4
-rw-r--r--MediaBrowser.Api/ItemRefreshService.cs9
-rw-r--r--MediaBrowser.Api/ItemUpdateService.cs1
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs10
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs138
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs5
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs9
-rw-r--r--MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs6
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs1
-rw-r--r--MediaBrowser.Api/Playback/Progressive/AudioService.cs37
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs2
-rw-r--r--MediaBrowser.Api/Playback/StreamState.cs2
-rw-r--r--MediaBrowser.Api/PlaylistService.cs2
-rw-r--r--MediaBrowser.Api/Reports/ReportsService.cs5
-rw-r--r--MediaBrowser.Api/SearchService.cs48
-rw-r--r--MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs2
-rw-r--r--MediaBrowser.Api/SimilarItemsHelper.cs2
-rw-r--r--MediaBrowser.Api/StartupWizardService.cs2
-rw-r--r--MediaBrowser.Api/Subtitles/SubtitleService.cs2
-rw-r--r--MediaBrowser.Api/TvShowsService.cs10
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemsService.cs10
-rw-r--r--MediaBrowser.Api/UserLibrary/UserLibraryService.cs2
-rw-r--r--MediaBrowser.Api/UserService.cs8
-rw-r--r--MediaBrowser.Controller/Entities/Audio/Audio.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicGenre.cs2
-rw-r--r--MediaBrowser.Controller/Entities/AudioBook.cs4
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs33
-rw-r--r--MediaBrowser.Controller/Entities/Book.cs4
-rw-r--r--MediaBrowser.Controller/Entities/CollectionFolder.cs6
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs27
-rw-r--r--MediaBrowser.Controller/Entities/Game.cs2
-rw-r--r--MediaBrowser.Controller/Entities/GameGenre.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Genre.cs2
-rw-r--r--MediaBrowser.Controller/Entities/IHasSeries.cs1
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs4
-rw-r--r--MediaBrowser.Controller/Entities/LinkedChild.cs10
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs6
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs5
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs7
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs29
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs55
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs2
-rw-r--r--MediaBrowser.Controller/Library/ItemResolveArgs.cs6
-rw-r--r--MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs1
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvChannel.cs6
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs88
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs12
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs1
-rw-r--r--MediaBrowser.Controller/Playlists/Playlist.cs29
-rw-r--r--MediaBrowser.Controller/Providers/DirectoryService.cs6
-rw-r--r--MediaBrowser.Controller/Providers/IProviderManager.cs11
-rw-r--r--MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs2
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs23
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs2
-rw-r--r--MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs2
-rw-r--r--MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs2
-rw-r--r--MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs2
-rw-r--r--MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs15
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs61
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs4
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs5
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs45
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs7
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs3
-rw-r--r--MediaBrowser.Model/Dlna/ResolutionNormalizer.cs35
-rw-r--r--MediaBrowser.Model/Dto/BaseItemDto.cs6
-rw-r--r--MediaBrowser.Model/Dto/MediaSourceInfo.cs2
-rw-r--r--MediaBrowser.Model/IO/IFileSystem.cs2
-rw-r--r--MediaBrowser.Model/Querying/ItemFields.cs7
-rw-r--r--MediaBrowser.Model/Search/SearchHint.cs11
-rw-r--r--MediaBrowser.Model/Search/SearchQuery.cs11
-rw-r--r--MediaBrowser.Model/Session/GeneralCommandType.cs3
-rw-r--r--MediaBrowser.Model/Users/UserPolicy.cs2
-rw-r--r--MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs2
-rw-r--r--MediaBrowser.Providers/ImagesByName/ImageUtils.cs33
-rw-r--r--MediaBrowser.Providers/Manager/GenericPriorityQueue.cs429
-rw-r--r--MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs28
-rw-r--r--MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs28
-rw-r--r--MediaBrowser.Providers/Manager/IPriorityQueue.cs59
-rw-r--r--MediaBrowser.Providers/Manager/ImageSaver.cs10
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs13
-rw-r--r--MediaBrowser.Providers/Manager/ProviderUtils.cs42
-rw-r--r--MediaBrowser.Providers/Manager/SimplePriorityQueue.cs251
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj5
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs2
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs7
-rw-r--r--MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs3
-rw-r--r--MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs2
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbProvider.cs9
-rw-r--r--MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs3
-rw-r--r--MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs2
-rw-r--r--MediaBrowser.Providers/Music/AudioDbArtistProvider.cs4
-rw-r--r--MediaBrowser.Providers/Music/FanArtArtistProvider.cs4
-rw-r--r--MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs6
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbProvider.cs38
-rw-r--r--MediaBrowser.Providers/People/MovieDbPersonProvider.cs2
-rw-r--r--MediaBrowser.Providers/Studios/StudiosImageProvider.cs17
-rw-r--r--MediaBrowser.Providers/Subtitles/SubtitleManager.cs9
-rw-r--r--MediaBrowser.Providers/TV/DummySeasonProvider.cs7
-rw-r--r--MediaBrowser.Providers/TV/EpisodeMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs3
-rw-r--r--MediaBrowser.Providers/TV/MissingEpisodeProvider.cs19
-rw-r--r--MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs5
-rw-r--r--MediaBrowser.Providers/TV/SeasonMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs5
-rw-r--r--MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs2
-rw-r--r--MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs4
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs3
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs5
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs2
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs3
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs3
-rw-r--r--MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs5
-rw-r--r--MediaBrowser.Server.Mac.sln22
-rw-r--r--MediaBrowser.Server.Mac/Emby.Server.Mac.csproj222
-rw-r--r--MediaBrowser.Server.Mac/ImageMagickSharp.dll.config3
-rw-r--r--MediaBrowser.Server.Mac/MacAppHost.cs2
-rw-r--r--MediaBrowser.Server.Mac/Main.cs12
-rw-r--r--MediaBrowser.Server.Mono/ImageEncoderHelper.cs (renamed from MediaBrowser.Server.Startup.Common/ImageEncoderHelper.cs)0
-rw-r--r--MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj1
-rw-r--r--MediaBrowser.Server.Mono/MonoAppHost.cs2
-rw-r--r--MediaBrowser.Server.Mono/Program.cs11
-rw-r--r--MediaBrowser.Server.Mono/app.config2
-rw-r--r--MediaBrowser.Server.Startup.Common/Cryptography/CertificateGenerator.cs4
-rw-r--r--MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj17
-rw-r--r--MediaBrowser.Server.Startup.Common/packages.config2
-rw-r--r--MediaBrowser.ServerApplication/ImageEncoderHelper.cs48
-rw-r--r--MediaBrowser.ServerApplication/MainStartup.cs4
-rw-r--r--MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj1
-rw-r--r--MediaBrowser.ServerApplication/Native/LoopUtil.cs46
-rw-r--r--MediaBrowser.ServerApplication/WindowsAppHost.cs2
-rw-r--r--MediaBrowser.WebDashboard/Api/PackageCreator.cs4
-rw-r--r--MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs23
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs15
-rw-r--r--Nuget/MediaBrowser.Common.nuspec2
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec4
-rw-r--r--SocketHttpListener.Portable/Net/HttpConnection.cs2
-rw-r--r--SocketHttpListener.Portable/Net/HttpListenerResponse.cs2
-rw-r--r--SocketHttpListener.Portable/Net/ResponseStream.cs58
199 files changed, 1930 insertions, 1462 deletions
diff --git a/BDInfo/BDROM.cs b/BDInfo/BDROM.cs
index 123d1afe5..d86648364 100644
--- a/BDInfo/BDROM.cs
+++ b/BDInfo/BDROM.cs
@@ -96,7 +96,7 @@ namespace BDInfo
}
DirectoryRoot =
- _fileSystem.GetDirectoryInfo(Path.GetDirectoryName(DirectoryBDMV.FullName));
+ _fileSystem.GetDirectoryInfo(_fileSystem.GetDirectoryName(DirectoryBDMV.FullName));
DirectoryBDJO =
GetDirectory("BDJO", DirectoryBDMV, 0);
DirectoryCLIPINF =
@@ -349,7 +349,7 @@ namespace BDInfo
{
return dir;
}
- var parentFolder = Path.GetDirectoryName(dir.FullName);
+ var parentFolder = _fileSystem.GetDirectoryName(dir.FullName);
if (string.IsNullOrEmpty(parentFolder))
{
dir = null;
diff --git a/Emby.Common.Implementations/Devices/DeviceId.cs b/Emby.Common.Implementations/Devices/DeviceId.cs
index 3d23ab872..1de76456c 100644
--- a/Emby.Common.Implementations/Devices/DeviceId.cs
+++ b/Emby.Common.Implementations/Devices/DeviceId.cs
@@ -57,7 +57,7 @@ namespace Emby.Common.Implementations.Devices
{
var path = CachePath;
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_syncLock)
{
diff --git a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs
index ad6e35700..27fc642f1 100644
--- a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs
+++ b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs
@@ -131,4 +131,4 @@ namespace Emby.Common.Implementations.EnvironmentInfo
Environment.SetEnvironmentVariable(name, value);
}
}
-}
+} \ No newline at end of file
diff --git a/Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs
index 23f33f06c..eb9bc1bd0 100644
--- a/Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs
+++ b/Emby.Common.Implementations/HttpClientManager/HttpClientManager.cs
@@ -418,7 +418,7 @@ namespace Emby.Common.Implementations.HttpClientManager
private async Task CacheResponse(HttpResponseInfo response, string responseCachePath)
{
- _fileSystem.CreateDirectory(Path.GetDirectoryName(responseCachePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(responseCachePath));
using (var responseStream = response.Content)
{
diff --git a/Emby.Common.Implementations/IO/ManagedFileSystem.cs b/Emby.Common.Implementations/IO/ManagedFileSystem.cs
index ba73c1ba2..3ed4f650f 100644
--- a/Emby.Common.Implementations/IO/ManagedFileSystem.cs
+++ b/Emby.Common.Implementations/IO/ManagedFileSystem.cs
@@ -546,24 +546,6 @@ namespace Emby.Common.Implementations.IO
return Path.DirectorySeparatorChar;
}
- public bool AreEqual(string path1, string path2)
- {
- if (path1 == null && path2 == null)
- {
- return true;
- }
-
- if (path1 == null || path2 == null)
- {
- return false;
- }
-
- path1 = path1.TrimEnd(GetDirectorySeparatorChar(path1));
- path2 = path2.TrimEnd(GetDirectorySeparatorChar(path2));
-
- return string.Equals(path1, path2, StringComparison.OrdinalIgnoreCase);
- }
-
public bool ContainsSubPath(string parentPath, string path)
{
if (string.IsNullOrEmpty(parentPath))
@@ -588,7 +570,7 @@ namespace Emby.Common.Implementations.IO
throw new ArgumentNullException("path");
}
- var parent = Path.GetDirectoryName(path);
+ var parent = GetDirectoryName(path);
if (!string.IsNullOrEmpty(parent))
{
@@ -598,6 +580,16 @@ namespace Emby.Common.Implementations.IO
return true;
}
+ public string GetDirectoryName(string path)
+ {
+ if (_sharpCifsFileSystem.IsEnabledForPath(path))
+ {
+ return _sharpCifsFileSystem.GetDirectoryName(path);
+ }
+
+ return Path.GetDirectoryName(path);
+ }
+
public string NormalizePath(string path)
{
if (string.IsNullOrEmpty(path))
@@ -605,6 +597,11 @@ namespace Emby.Common.Implementations.IO
throw new ArgumentNullException("path");
}
+ if (_sharpCifsFileSystem.IsEnabledForPath(path))
+ {
+ return _sharpCifsFileSystem.NormalizePath(path);
+ }
+
if (path.EndsWith(":\\", StringComparison.OrdinalIgnoreCase))
{
return path;
@@ -613,6 +610,21 @@ namespace Emby.Common.Implementations.IO
return path.TrimEnd(GetDirectorySeparatorChar(path));
}
+ public bool AreEqual(string path1, string path2)
+ {
+ if (path1 == null && path2 == null)
+ {
+ return true;
+ }
+
+ if (path1 == null || path2 == null)
+ {
+ return false;
+ }
+
+ return string.Equals(NormalizePath(path1), NormalizePath(path2), StringComparison.OrdinalIgnoreCase);
+ }
+
public string GetFileNameWithoutExtension(FileSystemMetadata info)
{
if (info.IsDirectory)
@@ -637,11 +649,17 @@ namespace Emby.Common.Implementations.IO
// Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\
+ if (_sharpCifsFileSystem.IsEnabledForPath(path))
+ {
+ return true;
+ }
+
if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
!path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
{
return false;
}
+
return true;
//return Path.IsPathRooted(path);
diff --git a/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs b/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs
index c1e429dc9..0a407d64f 100644
--- a/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs
+++ b/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs
@@ -30,6 +30,34 @@ namespace Emby.Common.Implementations.IO
return path.StartsWith("smb://", StringComparison.OrdinalIgnoreCase) || IsUncPath(path);
}
+ public string NormalizePath(string path)
+ {
+ if (path.StartsWith("smb://", StringComparison.OrdinalIgnoreCase))
+ {
+ return path;
+ }
+
+ if (IsUncPath(path))
+ {
+ return ConvertUncToSmb(path);
+ }
+
+ return path;
+ }
+
+ public string GetDirectoryName(string path)
+ {
+ var separator = GetDirectorySeparatorChar(path);
+ var result = Path.GetDirectoryName(path);
+
+ if (separator == '/')
+ {
+ result = result.Replace('\\', '/');
+ }
+
+ return result;
+ }
+
public char GetDirectorySeparatorChar(string path)
{
if (path.IndexOf('/') != -1)
diff --git a/Emby.Common.Implementations/Net/NetAcceptSocket.cs b/Emby.Common.Implementations/Net/NetAcceptSocket.cs
index 3721709e6..82e7e9b00 100644
--- a/Emby.Common.Implementations/Net/NetAcceptSocket.cs
+++ b/Emby.Common.Implementations/Net/NetAcceptSocket.cs
@@ -100,7 +100,7 @@ namespace Emby.Common.Implementations.Net
#if NET46
public Task SendFile(string path, byte[] preBuffer, byte[] postBuffer, CancellationToken cancellationToken)
{
- var options = TransmitFileOptions.UseKernelApc;
+ var options = TransmitFileOptions.UseDefaultWorkerThread;
var completionSource = new TaskCompletionSource<bool>();
diff --git a/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
index f0518f69e..ac1c55b6b 100644
--- a/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
+++ b/Emby.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
@@ -158,7 +158,7 @@ namespace Emby.Common.Implementations.ScheduledTasks
_lastExecutionResult = value;
var path = GetHistoryFilePath();
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_lastExecutionResultSyncLock)
{
@@ -575,7 +575,7 @@ namespace Emby.Common.Implementations.ScheduledTasks
{
var path = GetConfigurationFilePath();
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
JsonSerializer.SerializeToFile(triggers, path);
}
diff --git a/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs
index 77482d56b..500f57aad 100644
--- a/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs
+++ b/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs
@@ -91,7 +91,7 @@ namespace Emby.Drawing.ImageMagick
try
{
var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp");
- _fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
using (var wand = new MagickWand(1, 1, new PixelWand("none", 1)))
{
diff --git a/Emby.Drawing.ImageMagick/PlayedIndicatorDrawer.cs b/Emby.Drawing.ImageMagick/PlayedIndicatorDrawer.cs
index 14fb0ddf1..58c6cfe82 100644
--- a/Emby.Drawing.ImageMagick/PlayedIndicatorDrawer.cs
+++ b/Emby.Drawing.ImageMagick/PlayedIndicatorDrawer.cs
@@ -68,7 +68,7 @@ namespace Emby.Drawing.ImageMagick
var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name;
var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf");
- fileSystem.CreateDirectory(Path.GetDirectoryName(tempPath));
+ fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath));
using (var stream = typeof(PlayedIndicatorDrawer).Assembly.GetManifestResourceStream(namespacePath))
{
@@ -78,7 +78,7 @@ namespace Emby.Drawing.ImageMagick
}
}
- fileSystem.CreateDirectory(Path.GetDirectoryName(filePath));
+ fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
try
{
@@ -108,7 +108,7 @@ namespace Emby.Drawing.ImageMagick
}).ConfigureAwait(false);
- fileSystem.CreateDirectory(Path.GetDirectoryName(filePath));
+ fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
try
{
diff --git a/Emby.Drawing.Net/GDIImageEncoder.cs b/Emby.Drawing.Net/GDIImageEncoder.cs
index 831a57979..638415afd 100644
--- a/Emby.Drawing.Net/GDIImageEncoder.cs
+++ b/Emby.Drawing.Net/GDIImageEncoder.cs
@@ -81,7 +81,7 @@ namespace Emby.Drawing.Net
{
using (var croppedImage = image.CropWhitespace())
{
- _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath));
using (var outputStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
{
@@ -135,7 +135,7 @@ namespace Emby.Drawing.Net
var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
// Save to the cache location
using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs
index f19e3e037..bee0e9b69 100644
--- a/Emby.Drawing/ImageProcessor.cs
+++ b/Emby.Drawing/ImageProcessor.cs
@@ -244,9 +244,9 @@ namespace Emby.Drawing
var newWidth = Convert.ToInt32(newSize.Width);
var newHeight = Convert.ToInt32(newSize.Height);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
- _fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
_imageEncoder.EncodeImage(originalImagePath, tmpPath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat);
CopyFile(tmpPath, cacheFilePath);
@@ -418,9 +418,9 @@ namespace Emby.Drawing
try
{
- _fileSystem.CreateDirectory(Path.GetDirectoryName(croppedImagePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(croppedImagePath));
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(croppedImagePath));
- _fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
_imageEncoder.CropWhiteSpace(originalImagePath, tmpPath);
CopyFile(tmpPath, croppedImagePath);
@@ -592,7 +592,7 @@ namespace Emby.Drawing
try
{
var path = ImageSizeFile;
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(_cachedImagedSizes, path);
}
catch (Exception ex)
@@ -765,10 +765,10 @@ namespace Emby.Drawing
return enhancedImagePath;
}
- _fileSystem.CreateDirectory(Path.GetDirectoryName(enhancedImagePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath));
var tmpPath = Path.Combine(_appPaths.TempDirectory, Path.ChangeExtension(Guid.NewGuid().ToString(), Path.GetExtension(enhancedImagePath)));
- _fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, tmpPath, item, imageType, imageIndex).ConfigureAwait(false);
diff --git a/Emby.Server.Core/ApplicationHost.cs b/Emby.Server.Core/ApplicationHost.cs
index b7309de66..78bdc1189 100644
--- a/Emby.Server.Core/ApplicationHost.cs
+++ b/Emby.Server.Core/ApplicationHost.cs
@@ -257,7 +257,7 @@ namespace Emby.Server.Core
internal IPowerManagement PowerManagement { get; private set; }
internal IImageEncoder ImageEncoder { get; private set; }
- private readonly Action<string, string> _certificateGenerator;
+ private readonly Action<string, string, string> _certificateGenerator;
private readonly Func<string> _defaultUserNameFactory;
/// <summary>
@@ -274,7 +274,7 @@ namespace Emby.Server.Core
ISystemEvents systemEvents,
IMemoryStreamFactory memoryStreamFactory,
INetworkManager networkManager,
- Action<string, string> certificateGenerator,
+ Action<string, string, string> certificateGenerator,
Func<string> defaultUsernameFactory)
: base(applicationPaths,
logManager,
@@ -609,8 +609,8 @@ namespace Emby.Server.Core
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
- CertificatePath = GetCertificatePath(true);
- Certificate = GetCertificate(CertificatePath);
+ CertificateInfo = GetCertificateInfo(true);
+ Certificate = GetCertificate(CertificateInfo);
HttpServer = HttpServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, NetworkManager, MemoryStreamFactory, "Emby", "web/index.html", textEncoding, SocketFactory, CryptographyProvider, JsonSerializer, XmlSerializer, EnvironmentInfo, Certificate, FileSystemManager, SupportsDualModeSockets);
HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
@@ -745,8 +745,10 @@ namespace Emby.Server.Core
}
}
- private ICertificate GetCertificate(string certificateLocation)
+ private ICertificate GetCertificate(CertificateInfo info)
{
+ var certificateLocation = info == null ? null : info.Path;
+
if (string.IsNullOrWhiteSpace(certificateLocation))
{
return null;
@@ -759,7 +761,7 @@ namespace Emby.Server.Core
return null;
}
- X509Certificate2 localCert = new X509Certificate2(certificateLocation);
+ X509Certificate2 localCert = new X509Certificate2(certificateLocation, info.Password);
//localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
if (!localCert.HasPrivateKey)
{
@@ -1064,7 +1066,7 @@ namespace Emby.Server.Core
SyncManager.AddParts(GetExports<ISyncProvider>());
}
- private string CertificatePath { get; set; }
+ private CertificateInfo CertificateInfo { get; set; }
private ICertificate Certificate { get; set; }
private IEnumerable<string> GetUrlPrefixes()
@@ -1080,7 +1082,7 @@ namespace Emby.Server.Core
"http://"+i+":" + HttpPort + "/"
};
- if (!string.IsNullOrWhiteSpace(CertificatePath))
+ if (CertificateInfo != null)
{
prefixes.Add("https://" + i + ":" + HttpsPort + "/");
}
@@ -1123,27 +1125,31 @@ namespace Emby.Server.Core
}
}
- private string GetCertificatePath(bool generateCertificate)
+ private CertificateInfo GetCertificateInfo(bool generateCertificate)
{
if (!string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.CertificatePath))
{
// Custom cert
- return ServerConfigurationManager.Configuration.CertificatePath;
+ return new CertificateInfo
+ {
+ Path = ServerConfigurationManager.Configuration.CertificatePath
+ };
}
// Generate self-signed cert
var certHost = GetHostnameFromExternalDns(ServerConfigurationManager.Configuration.WanDdns);
- var certPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.ProgramDataPath, "ssl", "cert_" + (certHost + "1").GetMD5().ToString("N") + ".pfx");
+ var certPath = Path.Combine(ServerConfigurationManager.ApplicationPaths.ProgramDataPath, "ssl", "cert_" + (certHost + "2").GetMD5().ToString("N") + ".pfx");
+ var password = "embycert";
if (generateCertificate)
{
if (!FileSystemManager.FileExists(certPath))
{
- FileSystemManager.CreateDirectory(Path.GetDirectoryName(certPath));
+ FileSystemManager.CreateDirectory(FileSystemManager.GetDirectoryName(certPath));
try
{
- _certificateGenerator(certPath, certHost);
+ _certificateGenerator(certPath, certHost, password);
}
catch (Exception ex)
{
@@ -1153,7 +1159,11 @@ namespace Emby.Server.Core
}
}
- return certPath;
+ return new CertificateInfo
+ {
+ Path = certPath,
+ Password = password
+ };
}
/// <summary>
@@ -1189,7 +1199,11 @@ namespace Emby.Server.Core
requiresRestart = true;
}
- if (!string.Equals(CertificatePath, GetCertificatePath(false), StringComparison.OrdinalIgnoreCase))
+ var currentCertPath = CertificateInfo == null ? null : CertificateInfo.Path;
+ var newCertInfo = GetCertificateInfo(false);
+ var newCertPath = newCertInfo == null ? null : newCertInfo.Path;
+
+ if (!string.Equals(currentCertPath, newCertPath, StringComparison.OrdinalIgnoreCase))
{
requiresRestart = true;
}
@@ -1779,6 +1793,11 @@ namespace Emby.Server.Core
{
Container.Register(typeInterface, typeImplementation);
}
+ }
+ internal class CertificateInfo
+ {
+ public string Path { get; set; }
+ public string Password { get; set; }
}
}
diff --git a/Emby.Server.Core/IO/LibraryMonitor.cs b/Emby.Server.Core/IO/LibraryMonitor.cs
index ae7b66597..0f6a2e9a2 100644
--- a/Emby.Server.Core/IO/LibraryMonitor.cs
+++ b/Emby.Server.Core/IO/LibraryMonitor.cs
@@ -453,7 +453,7 @@ namespace Emby.Server.Core.IO
// If the parent of an ignored path has a change event, ignore that too
if (tempIgnorePaths.Any(i =>
{
- if (string.Equals(i, path, StringComparison.OrdinalIgnoreCase))
+ if (_fileSystem.AreEqual(i, path))
{
Logger.Debug("Ignoring change to {0}", path);
return true;
@@ -466,10 +466,10 @@ namespace Emby.Server.Core.IO
}
// Go up a level
- var parent = Path.GetDirectoryName(i);
+ var parent = _fileSystem.GetDirectoryName(i);
if (!string.IsNullOrEmpty(parent))
{
- if (string.Equals(parent, path, StringComparison.OrdinalIgnoreCase))
+ if (_fileSystem.AreEqual(parent, path))
{
Logger.Debug("Ignoring change to {0}", path);
return true;
@@ -492,7 +492,7 @@ namespace Emby.Server.Core.IO
private void CreateRefresher(string path)
{
- var parentPath = Path.GetDirectoryName(path);
+ var parentPath = _fileSystem.GetDirectoryName(path);
lock (_activeRefreshers)
{
@@ -500,7 +500,7 @@ namespace Emby.Server.Core.IO
foreach (var refresher in refreshers)
{
// Path is already being refreshed
- if (string.Equals(path, refresher.Path, StringComparison.Ordinal))
+ if (_fileSystem.AreEqual(path, refresher.Path))
{
refresher.RestartTimer();
return;
@@ -521,7 +521,7 @@ namespace Emby.Server.Core.IO
}
// They are siblings. Rebase the refresher to the parent folder.
- if (string.Equals(parentPath, Path.GetDirectoryName(refresher.Path), StringComparison.Ordinal))
+ if (string.Equals(parentPath, _fileSystem.GetDirectoryName(refresher.Path), StringComparison.Ordinal))
{
refresher.ResetPath(parentPath, path);
return;
diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs
index 8f03fa7a4..0cdd934b7 100644
--- a/Emby.Server.Implementations/Channels/ChannelManager.cs
+++ b/Emby.Server.Implementations/Channels/ChannelManager.cs
@@ -268,24 +268,14 @@ namespace Emby.Server.Implementations.Channels
return;
}
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(mediaSources, path);
}
public async Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, CancellationToken cancellationToken)
{
- IEnumerable<ChannelMediaInfo> results = new List<ChannelMediaInfo>();
- var video = item as Video;
- if (video != null)
- {
- results = video.ChannelMediaSources;
- }
- var audio = item as Audio;
- if (audio != null)
- {
- results = audio.ChannelMediaSources ?? GetSavedMediaSources(audio);
- }
+ IEnumerable<ChannelMediaInfo> results = GetSavedMediaSources(item);
return SortMediaInfoResults(results)
.Select(i => GetMediaSource(item, i))
@@ -1115,7 +1105,7 @@ namespace Emby.Server.Implementations.Channels
{
try
{
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(result, path);
}
@@ -1378,7 +1368,6 @@ namespace Emby.Server.Implementations.Channels
if (channelVideoItem != null)
{
channelVideoItem.ExtraType = info.ExtraType;
- channelVideoItem.ChannelMediaSources = info.MediaSources;
var mediaSource = info.MediaSources.FirstOrDefault();
item.Path = mediaSource == null ? null : mediaSource.Path;
@@ -1427,7 +1416,7 @@ namespace Emby.Server.Implementations.Channels
if (!_refreshedItems.ContainsKey(program.Id))
{
_refreshedItems.TryAdd(program.Id, true);
- _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem));
+ _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low);
}
}
diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs
index d0bd76c35..9c26655fc 100644
--- a/Emby.Server.Implementations/Collections/CollectionManager.cs
+++ b/Emby.Server.Implementations/Collections/CollectionManager.cs
@@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Collections
}
else
{
- _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem));
+ _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
}
EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs
@@ -191,7 +191,7 @@ namespace Emby.Server.Implementations.Collections
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
- _providerManager.QueueRefresh(collection.Id, refreshOptions);
+ _providerManager.QueueRefresh(collection.Id, refreshOptions, RefreshPriority.High);
if (fireEvent)
{
@@ -244,7 +244,7 @@ namespace Emby.Server.Implementations.Collections
collection.UpdateRatingToContent();
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
- _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem));
+ _providerManager.QueueRefresh(collection.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs
{
diff --git a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
index 0096f2284..e25955782 100644
--- a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
+++ b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
@@ -71,10 +71,9 @@ namespace Emby.Server.Implementations.Data
double newPercentCommplete = 45 + .55 * p;
progress.Report(newPercentCommplete);
});
- await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false);
- progress.Report(100);
await _itemRepo.UpdateInheritedValues(cancellationToken).ConfigureAwait(false);
+ progress.Report(100);
}
private async Task CleanDeadItems(CancellationToken cancellationToken, IProgress<double> progress)
@@ -115,115 +114,6 @@ namespace Emby.Server.Implementations.Data
progress.Report(100);
}
- private async Task CleanDeletedItems(CancellationToken cancellationToken, IProgress<double> progress)
- {
- var result = _itemRepo.GetItemIdsWithPath(new InternalItemsQuery
- {
- LocationTypes = new[] { LocationType.FileSystem },
- //Limit = limit,
-
- // These have their own cleanup routines
- ExcludeItemTypes = new[]
- {
- typeof(Person).Name,
- typeof(Genre).Name,
- typeof(MusicGenre).Name,
- typeof(GameGenre).Name,
- typeof(Studio).Name,
- typeof(Year).Name,
- typeof(Channel).Name,
- typeof(AggregateFolder).Name,
- typeof(CollectionFolder).Name
- }
- });
-
- var numComplete = 0;
- var numItems = result.Count;
-
- var allLibraryPaths = _libraryManager
- .GetVirtualFolders()
- .SelectMany(i => i.Locations)
- .ToList();
-
- foreach (var item in result)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- var path = item.Item2;
-
- try
- {
- var isPathInLibrary = false;
-
- if (allLibraryPaths.Any(i => path.StartsWith(i, StringComparison.Ordinal)) ||
- allLibraryPaths.Contains(path, StringComparer.Ordinal) ||
- path.StartsWith(_appPaths.ProgramDataPath, StringComparison.Ordinal))
- {
- isPathInLibrary = true;
-
- if (_fileSystem.FileExists(path) || _fileSystem.DirectoryExists(path))
- {
- continue;
- }
- }
-
- var libraryItem = _libraryManager.GetItemById(item.Item1);
-
- if (libraryItem == null)
- {
- continue;
- }
-
- if (libraryItem.IsTopParent)
- {
- continue;
- }
-
- var hasDualAccess = libraryItem as IHasDualAccess;
- if (hasDualAccess != null && hasDualAccess.IsAccessedByName)
- {
- continue;
- }
-
- var libraryItemPath = libraryItem.Path;
- if (!string.Equals(libraryItemPath, path, StringComparison.OrdinalIgnoreCase))
- {
- _logger.Error("CleanDeletedItems aborting delete for item {0}-{1} because paths don't match. {2}---{3}", libraryItem.Id, libraryItem.Name, libraryItem.Path ?? string.Empty, path ?? string.Empty);
- continue;
- }
-
- if (Folder.IsPathOffline(path, allLibraryPaths))
- {
- continue;
- }
-
- if (isPathInLibrary)
- {
- _logger.Info("Deleting item from database {0} because path no longer exists. type: {1} path: {2}", libraryItem.Name, libraryItem.GetType().Name, libraryItemPath ?? string.Empty);
- }
- else
- {
- _logger.Info("Deleting item from database {0} because path is no longer in the server library. type: {1} path: {2}", libraryItem.Name, libraryItem.GetType().Name, libraryItemPath ?? string.Empty);
- }
-
- await libraryItem.OnFileDeleted().ConfigureAwait(false);
- }
- catch (OperationCanceledException)
- {
- throw;
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in CleanDeletedItems. File {0}", ex, path);
- }
-
- numComplete++;
- double percent = numComplete;
- percent /= numItems;
- progress.Report(percent * 100);
- }
- }
-
/// <summary>
/// Creates the triggers that define when the task will run
/// </summary>
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index 51f91acf3..61dce9bba 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -201,7 +201,6 @@ namespace Emby.Server.Implementations.Data
AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames);
- AddColumn(db, "TypedBaseItems", "OfficialRatingDescription", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "HomePageUrl", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "VoteCount", "INT", existingColumnNames);
AddColumn(db, "TypedBaseItems", "DisplayMediaType", "Text", existingColumnNames);
@@ -209,7 +208,6 @@ namespace Emby.Server.Implementations.Data
AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames);
AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames);
- AddColumn(db, "TypedBaseItems", "LocationType", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames);
AddColumn(db, "TypedBaseItems", "IsLive", "BIT", existingColumnNames);
@@ -240,7 +238,6 @@ namespace Emby.Server.Implementations.Data
AddColumn(db, "TypedBaseItems", "SourceType", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames);
- AddColumn(db, "TypedBaseItems", "CriticRatingSummary", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "InheritedTags", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "CleanName", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "PresentationUniqueKey", "Text", existingColumnNames);
@@ -255,7 +252,6 @@ namespace Emby.Server.Implementations.Data
AddColumn(db, "TypedBaseItems", "SeasonName", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "SeasonId", "GUID", existingColumnNames);
AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames);
- AddColumn(db, "TypedBaseItems", "SeriesSortName", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames);
AddColumn(db, "TypedBaseItems", "Keywords", "Text", existingColumnNames);
@@ -429,7 +425,6 @@ namespace Emby.Server.Implementations.Data
"ParentIndexNumber",
"ProductionYear",
"OfficialRating",
- "OfficialRatingDescription",
"HomePageUrl",
"DisplayMediaType",
"ForcedSortName",
@@ -454,13 +449,11 @@ namespace Emby.Server.Implementations.Data
"DateLastMediaAdded",
"Album",
"CriticRating",
- "CriticRatingSummary",
"IsVirtualItem",
"SeriesName",
"SeasonName",
"SeasonId",
"SeriesId",
- "SeriesSortName",
"PresentationUniqueKey",
"InheritedParentalRatingValue",
"InheritedTags",
@@ -552,14 +545,12 @@ namespace Emby.Server.Implementations.Data
"InheritedParentalRatingValue",
"SortName",
"RunTimeTicks",
- "OfficialRatingDescription",
"HomePageUrl",
"VoteCount",
"DisplayMediaType",
"DateCreated",
"DateModified",
"ForcedSortName",
- "LocationType",
"PreferredMetadataLanguage",
"PreferredMetadataCountryCode",
"IsHD",
@@ -579,7 +570,6 @@ namespace Emby.Server.Implementations.Data
"SourceType",
"TrailerTypes",
"CriticRating",
- "CriticRatingSummary",
"InheritedTags",
"CleanName",
"PresentationUniqueKey",
@@ -594,7 +584,6 @@ namespace Emby.Server.Implementations.Data
"SeasonName",
"SeasonId",
"SeriesId",
- "SeriesSortName",
"ExternalSeriesId",
"Tagline",
"Keywords",
@@ -833,7 +822,6 @@ namespace Emby.Server.Implementations.Data
saveItemStatement.TryBind("@SortName", item.SortName);
saveItemStatement.TryBind("@RunTimeTicks", item.RunTimeTicks);
- saveItemStatement.TryBind("@OfficialRatingDescription", item.OfficialRatingDescription);
saveItemStatement.TryBind("@HomePageUrl", item.HomePageUrl);
saveItemStatement.TryBind("@VoteCount", item.VoteCount);
saveItemStatement.TryBind("@DisplayMediaType", item.DisplayMediaType);
@@ -841,7 +829,6 @@ namespace Emby.Server.Implementations.Data
saveItemStatement.TryBind("@DateModified", item.DateModified);
saveItemStatement.TryBind("@ForcedSortName", item.ForcedSortName);
- saveItemStatement.TryBind("@LocationType", item.LocationType.ToString());
saveItemStatement.TryBind("@PreferredMetadataLanguage", item.PreferredMetadataLanguage);
saveItemStatement.TryBind("@PreferredMetadataCountryCode", item.PreferredMetadataCountryCode);
@@ -942,7 +929,6 @@ namespace Emby.Server.Implementations.Data
}
saveItemStatement.TryBind("@CriticRating", item.CriticRating);
- saveItemStatement.TryBind("@CriticRatingSummary", item.CriticRatingSummary);
var inheritedTags = item.InheritedTags;
if (inheritedTags.Count > 0)
@@ -1024,13 +1010,11 @@ namespace Emby.Server.Implementations.Data
if (hasSeries != null)
{
saveItemStatement.TryBind("@SeriesId", hasSeries.SeriesId);
- saveItemStatement.TryBind("@SeriesSortName", hasSeries.SeriesSortName);
saveItemStatement.TryBind("@SeriesPresentationUniqueKey", hasSeries.SeriesPresentationUniqueKey);
}
else
{
saveItemStatement.TryBindNull("@SeriesId");
- saveItemStatement.TryBindNull("@SeriesSortName");
saveItemStatement.TryBindNull("@SeriesPresentationUniqueKey");
}
@@ -1290,22 +1274,10 @@ namespace Emby.Server.Implementations.Data
{
return false;
}
- if (type == typeof(Year))
- {
- return false;
- }
- if (type == typeof(Book))
- {
- return false;
- }
if (type == typeof(Person))
{
return false;
}
- if (type == typeof(RecordingGroup))
- {
- return false;
- }
if (type == typeof(Channel))
{
return false;
@@ -1339,31 +1311,42 @@ namespace Emby.Server.Implementations.Data
return false;
}
}
- if (_config.Configuration.SkipDeserializationForPrograms)
+
+ if (type == typeof(Year))
+ {
+ return false;
+ }
+ if (type == typeof(Book))
{
- if (type == typeof(LiveTvProgram))
- {
- return false;
- }
+ return false;
+ }
+ if (type == typeof(RecordingGroup))
+ {
+ return false;
}
+ if (type == typeof(LiveTvProgram))
+ {
+ return false;
+ }
+ if (type == typeof(LiveTvAudioRecording))
+ {
+ return false;
+ }
+ if (type == typeof(AudioPodcast))
+ {
+ return false;
+ }
+ if (type == typeof(AudioBook))
+ {
+ return false;
+ }
+
if (_config.Configuration.SkipDeserializationForAudio)
{
if (type == typeof(Audio))
{
return false;
}
- if (type == typeof(LiveTvAudioRecording))
- {
- return false;
- }
- if (type == typeof(AudioPodcast))
- {
- return false;
- }
- if (type == typeof(AudioBook))
- {
- return false;
- }
if (type == typeof(MusicAlbum))
{
return false;
@@ -1609,15 +1592,6 @@ namespace Emby.Server.Implementations.Data
}
index++;
- if (query.HasField(ItemFields.OfficialRatingDescription))
- {
- if (!reader.IsDBNull(index))
- {
- item.OfficialRatingDescription = reader.GetString(index);
- }
- index++;
- }
-
if (query.HasField(ItemFields.HomePageUrl))
{
if (!reader.IsDBNull(index))
@@ -1803,15 +1777,6 @@ namespace Emby.Server.Implementations.Data
}
index++;
- if (query.HasField(ItemFields.CriticRatingSummary))
- {
- if (!reader.IsDBNull(index))
- {
- item.CriticRatingSummary = reader.GetString(index);
- }
- index++;
- }
-
if (!reader.IsDBNull(index))
{
item.IsVirtualItem = reader.GetBoolean(index);
@@ -1856,15 +1821,6 @@ namespace Emby.Server.Implementations.Data
}
index++;
- if (hasSeries != null)
- {
- if (!reader.IsDBNull(index))
- {
- hasSeries.SeriesSortName = reader.GetString(index);
- }
- }
- index++;
-
if (!reader.IsDBNull(index))
{
item.PresentationUniqueKey = reader.GetString(index);
@@ -2893,6 +2849,10 @@ namespace Emby.Server.Implementations.Data
{
return new Tuple<string, bool>("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false);
}
+ if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase))
+ {
+ return new Tuple<string, bool>("(Select SortName from TypedBaseItems where B.Guid=A.SeriesId)", false);
+ }
return new Tuple<string, bool>(name, false);
}
@@ -4100,27 +4060,6 @@ namespace Emby.Server.Implementations.Data
whereClauses.Add("ProductionYear in (" + val + ")");
}
- if (query.LocationTypes.Length == 1)
- {
- if (query.LocationTypes[0] == LocationType.Virtual && _config.Configuration.SchemaVersion >= 90)
- {
- query.IsVirtualItem = true;
- }
- else
- {
- whereClauses.Add("LocationType=@LocationType");
- if (statement != null)
- {
- statement.TryBind("@LocationType", query.LocationTypes[0].ToString());
- }
- }
- }
- else if (query.LocationTypes.Length > 1)
- {
- var val = string.Join(",", query.LocationTypes.Select(i => "'" + i + "'").ToArray());
-
- whereClauses.Add("LocationType in (" + val + ")");
- }
if (query.IsVirtualItem.HasValue)
{
whereClauses.Add("IsVirtualItem=@IsVirtualItem");
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index 7c0baf9c2..78d76fd76 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.Dto
if (fields.Contains(ItemFields.BasicSyncInfo) || fields.Contains(ItemFields.SyncInfo))
{
- var userCanSync = user != null && user.Policy.EnableSync;
+ var userCanSync = user != null && user.Policy.EnableContentDownloading;
if (userCanSync && _syncManager.SupportsSync(item))
{
dto.SupportsSync = true;
@@ -967,11 +967,6 @@ namespace Emby.Server.Implementations.Dto
dto.CriticRating = item.CriticRating;
- if (fields.Contains(ItemFields.CriticRatingSummary))
- {
- dto.CriticRatingSummary = item.CriticRatingSummary;
- }
-
var hasTrailers = item as IHasTrailers;
if (hasTrailers != null)
{
diff --git a/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
index 0a9c67285..86c8c5f68 100644
--- a/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
+++ b/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
@@ -352,7 +352,7 @@ namespace Emby.Server.Implementations.FileOrganization
_libraryMonitor.ReportFileSystemChangeBeginning(path);
var renameRelatedFiles = !hasRenamedFiles &&
- string.Equals(Path.GetDirectoryName(path), Path.GetDirectoryName(result.TargetPath), StringComparison.OrdinalIgnoreCase);
+ string.Equals(_fileSystem.GetDirectoryName(path), _fileSystem.GetDirectoryName(result.TargetPath), StringComparison.OrdinalIgnoreCase);
if (renameRelatedFiles)
{
@@ -432,7 +432,7 @@ namespace Emby.Server.Implementations.FileOrganization
// Now find other files
var originalFilenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
- var directory = Path.GetDirectoryName(path);
+ var directory = _fileSystem.GetDirectoryName(path);
if (!string.IsNullOrWhiteSpace(originalFilenameWithoutExtension) && !string.IsNullOrWhiteSpace(directory))
{
@@ -445,7 +445,7 @@ namespace Emby.Server.Implementations.FileOrganization
foreach (var file in files)
{
- directory = Path.GetDirectoryName(file);
+ directory = _fileSystem.GetDirectoryName(file);
var filename = Path.GetFileName(file);
filename = filename.Replace(originalFilenameWithoutExtension, targetFilenameWithoutExtension,
@@ -470,7 +470,7 @@ namespace Emby.Server.Implementations.FileOrganization
return new List<string>();
}
- var episodePaths = series.GetRecursiveChildren()
+ var episodePaths = series.GetRecursiveChildren(i => i is Episode)
.OfType<Episode>()
.Where(i =>
{
@@ -499,7 +499,7 @@ namespace Emby.Server.Implementations.FileOrganization
.Select(i => i.Path)
.ToList();
- var folder = Path.GetDirectoryName(targetPath);
+ var folder = _fileSystem.GetDirectoryName(targetPath);
var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath);
try
@@ -529,7 +529,7 @@ namespace Emby.Server.Implementations.FileOrganization
_libraryMonitor.ReportFileSystemChangeBeginning(result.TargetPath);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(result.TargetPath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(result.TargetPath));
var targetAlreadyExists = _fileSystem.FileExists(result.TargetPath);
diff --git a/Emby.Server.Implementations/HttpServer/FileWriter.cs b/Emby.Server.Implementations/HttpServer/FileWriter.cs
index dbaf97b1e..8cb7b5dbf 100644
--- a/Emby.Server.Implementations/HttpServer/FileWriter.cs
+++ b/Emby.Server.Implementations/HttpServer/FileWriter.cs
@@ -58,6 +58,7 @@ namespace Emby.Server.Implementations.HttpServer
Headers["Content-Type"] = contentType;
TotalContentLength = fileSystem.GetFileInfo(path).Length;
+ Headers["Accept-Ranges"] = "bytes";
if (string.IsNullOrWhiteSpace(rangeHeader))
{
@@ -66,7 +67,6 @@ namespace Emby.Server.Implementations.HttpServer
}
else
{
- Headers["Accept-Ranges"] = "bytes";
StatusCode = HttpStatusCode.PartialContent;
SetRangeValues();
}
@@ -96,8 +96,12 @@ namespace Emby.Server.Implementations.HttpServer
RangeLength = 1 + RangeEnd - RangeStart;
// Content-Length is the length of what we're serving, not the original content
- Headers["Content-Length"] = RangeLength.ToString(UsCulture);
- Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
+ var lengthString = RangeLength.ToString(UsCulture);
+ Headers["Content-Length"] = lengthString;
+ var rangeString = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
+ Headers["Content-Range"] = rangeString;
+
+ Logger.Info("Setting range response values for {0}. RangeRequest: {1} Content-Length: {2}, Content-Range: {3}", Path, RangeHeader, lengthString, rangeString);
}
/// <summary>
diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
index 310161d41..687bd62b0 100644
--- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
@@ -501,7 +501,7 @@ namespace Emby.Server.Implementations.HttpServer
private bool ShouldCompressResponse(IRequest requestContext, string contentType)
{
// It will take some work to support compression with byte range requests
- if (!string.IsNullOrEmpty(requestContext.Headers.Get("Range")))
+ if (!string.IsNullOrWhiteSpace(requestContext.Headers.Get("Range")))
{
return false;
}
@@ -566,7 +566,7 @@ namespace Emby.Server.Implementations.HttpServer
};
}
- if (!string.IsNullOrEmpty(rangeHeader))
+ if (!string.IsNullOrWhiteSpace(rangeHeader))
{
var stream = await factoryFn().ConfigureAwait(false);
@@ -621,6 +621,7 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders["Content-Encoding"] = requestedCompressionType;
}
+ responseHeaders["Vary"] = "Accept-Encoding";
responseHeaders["Content-Length"] = content.Length.ToString(UsCulture);
if (isHeadRequest)
diff --git a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs
index e88994bec..7c967949b 100644
--- a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs
+++ b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs
@@ -189,10 +189,15 @@ namespace Emby.Server.Implementations.HttpServer
private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength)
{
var array = new byte[BufferSize];
- int count;
- while ((count = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
+ int bytesRead;
+ while ((bytesRead = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
{
- var bytesToCopy = Math.Min(count, copyLength);
+ if (bytesRead == 0)
+ {
+ break;
+ }
+
+ var bytesToCopy = Math.Min(bytesRead, copyLength);
await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy)).ConfigureAwait(false);
diff --git a/Emby.Server.Implementations/HttpServer/ResponseFilter.cs b/Emby.Server.Implementations/HttpServer/ResponseFilter.cs
index 6d9d7d921..57eef5db0 100644
--- a/Emby.Server.Implementations/HttpServer/ResponseFilter.cs
+++ b/Emby.Server.Implementations/HttpServer/ResponseFilter.cs
@@ -26,8 +26,8 @@ namespace Emby.Server.Implementations.HttpServer
public void FilterResponse(IRequest req, IResponse res, object dto)
{
// Try to prevent compatibility view
- res.AddHeader("X-UA-Compatible", "IE=Edge");
- res.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Range, X-MediaBrowser-Token, X-Emby-Authorization");
+ //res.AddHeader("X-UA-Compatible", "IE=Edge");
+ res.AddHeader("Access-Control-Allow-Headers", "Accept, Accept-Language, Authorization, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, Content-Type, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, X-Emby-Authorization");
res.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
res.AddHeader("Access-Control-Allow-Origin", "*");
@@ -46,8 +46,6 @@ namespace Emby.Server.Implementations.HttpServer
}
}
- var vary = "Accept-Encoding";
-
var hasHeaders = dto as IHasHeaders;
var sharpResponse = res as WebSocketSharpResponse;
@@ -86,23 +84,9 @@ namespace Emby.Server.Implementations.HttpServer
}
}
}
-
- string hasHeadersVary;
- if (hasHeaders.Headers.TryGetValue("Vary", out hasHeadersVary))
- {
- vary = hasHeadersVary;
- }
-
- hasHeaders.Headers["Vary"] = vary;
}
//res.KeepAlive = false;
-
- // Per Google PageSpeed
- // This instructs the proxies to cache two versions of the resource: one compressed, and one uncompressed.
- // The correct version of the resource is delivered based on the client request header.
- // This is a good choice for applications that are singly homed and depend on public proxies for user locality.
- res.AddHeader("Vary", vary);
}
/// <summary>
diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs
index c64672685..033cbd8b0 100644
--- a/Emby.Server.Implementations/IO/FileRefresher.cs
+++ b/Emby.Server.Implementations/IO/FileRefresher.cs
@@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.IO
{
item = LibraryManager.FindByPath(path, null);
- path = System.IO.Path.GetDirectoryName(path);
+ path = _fileSystem.GetDirectoryName(path);
}
if (item != null)
diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs
index 38908c2bd..2677f7b2a 100644
--- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs
+++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs
@@ -139,7 +139,7 @@ namespace Emby.Server.Implementations.Images
CancellationToken cancellationToken)
{
var outputPathWithoutExtension = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid().ToString("N"));
- FileSystem.CreateDirectory(Path.GetDirectoryName(outputPathWithoutExtension));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPathWithoutExtension));
string outputPath = await CreateImage(item, itemsWithImages, outputPathWithoutExtension, imageType, 0).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(outputPath))
@@ -205,7 +205,7 @@ namespace Emby.Server.Implementations.Images
private async Task<string> CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height)
{
- FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath));
var options = new ImageCollageOptions
{
diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
index d782f5b88..64f025d93 100644
--- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
+++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
@@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.Library
{
if (parent == null)
{
- var parentFolderName = Path.GetFileName(Path.GetDirectoryName(path));
+ var parentFolderName = Path.GetFileName(_fileSystem.GetDirectoryName(path));
if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
{
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 16a73f392..685c794b7 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1962,8 +1962,34 @@ namespace Emby.Server.Implementations.Library
return new List<Folder>();
}
- return GetUserRootFolder().Children
- .OfType<Folder>()
+ return GetCollectionFoldersInternal(item, GetUserRootFolder().Children.OfType<Folder>().ToList());
+ }
+
+ public List<Folder> GetCollectionFolders(BaseItem item, List<Folder> allUserRootChildren)
+ {
+ while (item != null)
+ {
+ var parent = item.GetParent();
+
+ if (parent == null || parent is AggregateFolder)
+ {
+ break;
+ }
+
+ item = parent;
+ }
+
+ if (item == null)
+ {
+ return new List<Folder>();
+ }
+
+ return GetCollectionFoldersInternal(item, allUserRootChildren);
+ }
+
+ private List<Folder> GetCollectionFoldersInternal(BaseItem item, List<Folder> allUserRootChildren)
+ {
+ return allUserRootChildren
.Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path, StringComparer.OrdinalIgnoreCase))
.ToList();
}
@@ -2126,7 +2152,8 @@ namespace Emby.Server.Implementations.Library
// Not sure why this is necessary but need to figure it out
// View images are not getting utilized without this
ForceSave = true
- });
+
+ }, RefreshPriority.Normal);
}
return item;
@@ -2188,7 +2215,8 @@ namespace Emby.Server.Implementations.Library
{
// Need to force save to increment DateLastSaved
ForceSave = true
- });
+
+ }, RefreshPriority.Normal);
}
return item;
@@ -2252,7 +2280,8 @@ namespace Emby.Server.Implementations.Library
{
// Need to force save to increment DateLastSaved
ForceSave = true
- });
+
+ }, RefreshPriority.Normal);
}
return item;
@@ -2328,7 +2357,7 @@ namespace Emby.Server.Implementations.Library
{
// Need to force save to increment DateLastSaved
ForceSave = true
- });
+ }, RefreshPriority.Normal);
}
return item;
diff --git a/Emby.Server.Implementations/Library/MusicManager.cs b/Emby.Server.Implementations/Library/MusicManager.cs
index 9d07837c6..b15c01125 100644
--- a/Emby.Server.Implementations/Library/MusicManager.cs
+++ b/Emby.Server.Implementations/Library/MusicManager.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Controller.Playlists;
using System;
using System.Collections.Generic;
using System.Linq;
+using MediaBrowser.Model.Querying;
namespace Emby.Server.Implementations.Library
{
@@ -27,35 +28,14 @@ namespace Emby.Server.Implementations.Library
return list.Concat(GetInstantMixFromGenres(item.Genres, user));
}
- public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user)
+ public IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist item, User user)
{
- var genres = user.RootFolder
- .GetRecursiveChildren(user, new InternalItemsQuery(user)
- {
- IncludeItemTypes = new[] { typeof(Audio).Name }
- })
- .Cast<Audio>()
- .Where(i => i.HasAnyArtist(artist.Name))
- .SelectMany(i => i.Genres)
- .Concat(artist.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase);
-
- return GetInstantMixFromGenres(genres, user);
+ return GetInstantMixFromGenres(item.Genres, user);
}
public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user)
{
- var genres = item
- .GetRecursiveChildren(user, new InternalItemsQuery(user)
- {
- IncludeItemTypes = new[] { typeof(Audio).Name }
- })
- .Cast<Audio>()
- .SelectMany(i => i.Genres)
- .Concat(item.Genres)
- .DistinctNames();
-
- return GetInstantMixFromGenres(genres, user);
+ return GetInstantMixFromGenres(item.Genres, user);
}
public IEnumerable<Audio> GetInstantMixFromFolder(Folder item, User user)
@@ -63,7 +43,7 @@ namespace Emby.Server.Implementations.Library
var genres = item
.GetRecursiveChildren(user, new InternalItemsQuery(user)
{
- IncludeItemTypes = new[] {typeof(Audio).Name}
+ IncludeItemTypes = new[] { typeof(Audio).Name }
})
.Cast<Audio>()
.SelectMany(i => i.Genres)
@@ -75,41 +55,40 @@ namespace Emby.Server.Implementations.Library
public IEnumerable<Audio> GetInstantMixFromPlaylist(Playlist item, User user)
{
- var genres = item
- .GetRecursiveChildren(user, new InternalItemsQuery(user)
- {
- IncludeItemTypes = new[] { typeof(Audio).Name }
- })
- .Cast<Audio>()
- .SelectMany(i => i.Genres)
- .Concat(item.Genres)
- .DistinctNames();
-
- return GetInstantMixFromGenres(genres, user);
+ return GetInstantMixFromGenres(item.Genres, user);
}
public IEnumerable<Audio> GetInstantMixFromGenres(IEnumerable<string> genres, User user)
{
- var genreList = genres.ToList();
+ var genreIds = genres.DistinctNames().Select(i =>
+ {
+ try
+ {
+ return _libraryManager.GetMusicGenre(i).Id.ToString("N");
+ }
+ catch
+ {
+ return null;
+ }
+
+ }).Where(i => i != null);
- var inputItems = _libraryManager.GetItemList(new InternalItemsQuery(user)
+ return GetInstantMixFromGenreIds(genreIds, user);
+ }
+
+ public IEnumerable<Audio> GetInstantMixFromGenreIds(IEnumerable<string> genreIds, User user)
+ {
+ return _libraryManager.GetItemList(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Audio).Name },
- Genres = genreList.ToArray()
+ GenreIds = genreIds.ToArray(),
- });
+ Limit = 200,
- var genresDictionary = genreList.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
+ SortBy = new[] { ItemSortBy.Random }
- return inputItems
- .Cast<Audio>()
- .Select(i => new Tuple<Audio, int>(i, i.Genres.Count(genresDictionary.ContainsKey)))
- .OrderByDescending(i => i.Item2)
- .ThenBy(i => Guid.NewGuid())
- .Select(i => i.Item1)
- .Take(200)
- .OrderBy(i => Guid.NewGuid());
+ }).Cast<Audio>();
}
public IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user)
@@ -117,7 +96,7 @@ namespace Emby.Server.Implementations.Library
var genre = item as MusicGenre;
if (genre != null)
{
- return GetInstantMixFromGenres(new[] { item.Name }, user);
+ return GetInstantMixFromGenreIds(new[] { item.Id.ToString("N") }, user);
}
var playlist = item as Playlist;
diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
index 0968e8ea2..8bbda3b62 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
@@ -6,6 +6,7 @@ using System;
using System.IO;
using System.Linq;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.IO;
namespace Emby.Server.Implementations.Library.Resolvers
{
@@ -13,11 +14,13 @@ namespace Emby.Server.Implementations.Library.Resolvers
{
private readonly IImageProcessor _imageProcessor;
private readonly ILibraryManager _libraryManager;
+ private readonly IFileSystem _fileSystem;
- public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager)
+ public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_imageProcessor = imageProcessor;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -41,7 +44,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
var filename = Path.GetFileNameWithoutExtension(args.Path);
// Make sure the image doesn't belong to a video file
- if (args.DirectoryService.GetFilePaths(Path.GetDirectoryName(args.Path)).Any(i => IsOwnedByMedia(args.GetLibraryOptions(), i, filename)))
+ if (args.DirectoryService.GetFilePaths(_fileSystem.GetDirectoryName(args.Path)).Any(i => IsOwnedByMedia(args.GetLibraryOptions(), i, filename)))
{
return null;
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
index cf37366fb..bdab8552a 100644
--- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
@@ -57,7 +57,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
{
episode.SeriesId = series.Id;
episode.SeriesName = series.Name;
- episode.SeriesSortName = series.SortName;
}
if (season != null)
{
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
index c065feda1..84ceac65e 100644
--- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
@@ -44,7 +44,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
{
IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber,
SeriesId = series.Id,
- SeriesSortName = series.SortName,
SeriesName = series.Name
};
diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs
index a47a3322e..f640ae2b1 100644
--- a/Emby.Server.Implementations/Library/SearchEngine.cs
+++ b/Emby.Server.Implementations/Library/SearchEngine.cs
@@ -165,7 +165,16 @@ namespace Emby.Server.Implementations.Library
ExcludeItemTypes = excludeItemTypes.ToArray(),
IncludeItemTypes = includeItemTypes.ToArray(),
Limit = query.Limit,
- IncludeItemsByName = true
+ IncludeItemsByName = string.IsNullOrWhiteSpace(query.ParentId),
+ ParentId = string.IsNullOrWhiteSpace(query.ParentId) ? (Guid?)null : new Guid(query.ParentId),
+ SortBy = new[] { ItemSortBy.SortName },
+ Recursive = true,
+
+ IsKids = query.IsKids,
+ IsMovie = query.IsMovie,
+ IsNews = query.IsNews,
+ IsSeries = query.IsSeries,
+ IsSports = query.IsSports
});
// Add search hints based on item name
diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs
index 89b7198ca..0b9027291 100644
--- a/Emby.Server.Implementations/Library/UserManager.cs
+++ b/Emby.Server.Implementations/Library/UserManager.cs
@@ -942,7 +942,8 @@ namespace Emby.Server.Implementations.Library
{
return new UserPolicy
{
- EnableSync = true
+ EnableContentDownloading = true,
+ EnableSyncTranscoding = true
};
}
@@ -964,7 +965,7 @@ namespace Emby.Server.Implementations.Library
var path = GetPolifyFilePath(user);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_policySyncLock)
{
@@ -1051,7 +1052,7 @@ namespace Emby.Server.Implementations.Library
config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json);
}
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_configSyncLock)
{
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 666c1fdcd..f1b3f41b4 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -422,7 +422,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
if (!string.IsNullOrWhiteSpace(epgChannel.Name))
{
- tunerChannel.Name = epgChannel.Name;
+ //tunerChannel.Name = epgChannel.Name;
}
if (!string.IsNullOrWhiteSpace(epgChannel.ImageUrl))
{
@@ -1231,7 +1231,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
RequiresOpening = false,
RequiresClosing = false,
Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http,
- BufferMs = 0
+ BufferMs = 0,
+ IgnoreDts = true
};
var isAudio = false;
@@ -1496,7 +1497,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_libraryManager.RegisterIgnoredPath(recordPath);
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath));
activeRecordingInfo.Path = recordPath;
var duration = recordingEndDate - DateTime.UtcNow;
@@ -1516,8 +1517,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
EnforceKeepUpTo(timer, seriesPath);
};
- await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken)
- .ConfigureAwait(false);
+ await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken).ConfigureAwait(false);
recordingStatus = RecordingStatus.Completed;
_logger.Info("Recording completed: {0}", recordPath);
@@ -1725,7 +1725,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
while (FileExists(path, timerId))
{
- var parent = Path.GetDirectoryName(originalPath);
+ var parent = _fileSystem.GetDirectoryName(originalPath);
var name = Path.GetFileNameWithoutExtension(originalPath);
name += "-" + index.ToString(CultureInfo.InvariantCulture);
@@ -1765,7 +1765,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (regInfo.IsValid)
{
- return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient, _processFactory);
+ return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config, _httpClient, _processFactory, _config);
}
}
@@ -1892,7 +1892,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return;
}
- var imageSavePath = Path.Combine(Path.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension);
+ var imageSavePath = Path.Combine(_fileSystem.GetDirectoryName(recordingPath), imageSaveFilenameWithoutExtension);
// preserve original image extension
imageSavePath = Path.ChangeExtension(imageSavePath, Path.GetExtension(image.Path));
@@ -2155,11 +2155,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
writer.WriteElementString("mpaa", item.OfficialRating);
}
- if (!string.IsNullOrEmpty(item.OfficialRatingDescription))
- {
- writer.WriteElementString("mpaadescription", item.OfficialRatingDescription);
- }
-
var overview = (item.Overview ?? string.Empty)
.StripHtml()
.Replace("&quot;", "'");
@@ -2251,11 +2246,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture));
}
- if (!string.IsNullOrEmpty(item.CriticRatingSummary))
- {
- writer.WriteElementString("criticratingsummary", item.CriticRatingSummary);
- }
-
if (!string.IsNullOrWhiteSpace(item.Tagline))
{
writer.WriteElementString("tagline", item.Tagline);
@@ -2550,7 +2540,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private void SaveEpgDataForChannel(string channelId, List<ProgramInfo> epgData)
{
var path = GetChannelEpgCachePath(channelId);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_epgLock)
{
_jsonSerializer.SerializeToFile(epgData, path);
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index 6cc5b6920..790e6c27d 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -11,14 +11,16 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
-using MediaBrowser.Controller.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.MediaEncoding;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Diagnostics;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
+using MediaBrowser.Common.Configuration;
namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
@@ -37,8 +39,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private readonly IProcessFactory _processFactory;
private readonly IJsonSerializer _json;
private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
+ private readonly IServerConfigurationManager _config;
- public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions, IHttpClient httpClient, IProcessFactory processFactory)
+ public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions, IHttpClient httpClient, IProcessFactory processFactory, IServerConfigurationManager config)
{
_logger = logger;
_fileSystem = fileSystem;
@@ -48,6 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_liveTvOptions = liveTvOptions;
_httpClient = httpClient;
_processFactory = processFactory;
+ _config = config;
}
private string OutputFormat
@@ -76,23 +80,35 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile)
{
- return Path.ChangeExtension(targetFile, "." + OutputFormat);
+ var extension = OutputFormat;
+
+ if (string.Equals(extension, "mpegts", StringComparison.OrdinalIgnoreCase))
+ {
+ extension = "ts";
+ }
+
+ return Path.ChangeExtension(targetFile, "." + extension);
}
public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
{
- var durationToken = new CancellationTokenSource(duration);
- cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
+ //var durationToken = new CancellationTokenSource(duration);
+ //cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token;
await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false);
_logger.Info("Recording completed to file {0}", targetFile);
}
+ private EncodingOptions GetEncodingOptions()
+ {
+ return _config.GetConfiguration<EncodingOptions>("encoding");
+ }
+
private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken)
{
_targetPath = targetFile;
- _fileSystem.CreateDirectory(Path.GetDirectoryName(targetFile));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile));
var process = _processFactory.Create(new ProcessOptions
{
@@ -118,7 +134,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_logger.Info(commandLineLogMessage);
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt");
- _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(logFilePath));
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
_logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
@@ -162,28 +178,32 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
var durationParam = " -t " + _mediaEncoder.GetTimeParameter(duration.Ticks);
- var inputModifiers = "-fflags +genpts -async 1 -vsync -1";
- var commandLineArgs = "-i \"{0}\"{5} {2} -map_metadata -1 -threads 0 {3}{4}{6} -y \"{1}\"";
-
- long startTimeTicks = 0;
- //if (mediaSource.DateLiveStreamOpened.HasValue)
- //{
- // var elapsed = DateTime.UtcNow - mediaSource.DateLiveStreamOpened.Value;
- // elapsed -= TimeSpan.FromSeconds(10);
- // if (elapsed.TotalSeconds >= 0)
- // {
- // startTimeTicks = elapsed.Ticks + startTimeTicks;
- // }
- //}
- if (mediaSource.ReadAtNativeFramerate)
+ var flags = new List<string>();
+ if (mediaSource.IgnoreDts)
{
- inputModifiers += " -re";
+ flags.Add("+igndts");
+ }
+ if (mediaSource.IgnoreIndex)
+ {
+ flags.Add("+ignidx");
}
- if (startTimeTicks > 0)
+ var inputModifiers = "-async 1 -vsync -1";
+
+ if (flags.Count > 0)
+ {
+ inputModifiers += " -fflags " + string.Join("", flags.ToArray());
+ }
+
+ if (!string.IsNullOrWhiteSpace(GetEncodingOptions().HardwareAccelerationType))
+ {
+ inputModifiers += " -hwaccel auto";
+ }
+
+ if (mediaSource.ReadAtNativeFramerate)
{
- inputModifiers = "-ss " + _mediaEncoder.GetTimeParameter(startTimeTicks) + " " + inputModifiers;
+ inputModifiers += " -re";
}
var analyzeDurationSeconds = 5;
@@ -193,11 +213,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var subtitleArgs = CopySubtitles ? " -codec:s copy" : " -sn";
- var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ?
- " -f mp4 -movflags frag_keyframe+empty_moov" :
- string.Empty;
+ //var outputParam = string.Equals(Path.GetExtension(targetFile), ".mp4", StringComparison.OrdinalIgnoreCase) ?
+ // " -f mp4 -movflags frag_keyframe+empty_moov" :
+ // string.Empty;
+
+ var outputParam = string.Empty;
- commandLineArgs = string.Format(commandLineArgs, inputTempFile, targetFile, videoArgs, GetAudioArgs(mediaSource), subtitleArgs, durationParam, outputParam);
+ var commandLineArgs = string.Format("-i \"{0}\"{5} {2} -map_metadata -1 -threads 0 {3}{4}{6} -y \"{1}\"",
+ inputTempFile,
+ targetFile,
+ videoArgs,
+ GetAudioArgs(mediaSource),
+ subtitleArgs,
+ durationParam,
+ outputParam);
return inputModifiers + " " + commandLineArgs;
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
index 16ae26d45..953cb8e41 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
@@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
var file = _dataPath + ".json";
- _fileSystem.CreateDirectory(Path.GetDirectoryName(file));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(file));
lock (_fileDataLock)
{
diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
index fc0a826b4..b50f5ac92 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
@@ -86,7 +86,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
}).ConfigureAwait(false);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFile));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFile));
using (var stream = _fileSystem.OpenRead(tempFile))
{
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index a898d3084..fa86ac36d 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -857,7 +857,8 @@ namespace Emby.Server.Implementations.LiveTv
_providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem)
{
MetadataRefreshMode = metadataRefreshMode
- });
+
+ }, RefreshPriority.Normal);
}
return item.Id;
@@ -1395,11 +1396,11 @@ namespace Emby.Server.Implementations.LiveTv
foreach (var program in newPrograms)
{
- _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem));
+ _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low);
}
foreach (var program in updatedPrograms)
{
- _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem));
+ _providerManager.QueueRefresh(program.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.Low);
}
currentChannel.IsMovie = isMovie;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index 0a21603ee..d724a9fbc 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -420,7 +420,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
SupportsDirectPlay = false,
SupportsDirectStream = true,
SupportsTranscoding = true,
- IsInfiniteStream = true
+ IsInfiniteStream = true,
+ IgnoreDts = true
};
mediaSource.InferTotalBitrate();
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs
index abd7a00a9..02ebbcf16 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/MulticastStream.cs
@@ -29,6 +29,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
byte[] buffer = new byte[BufferSize];
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+
while (!cancellationToken.IsCancellationRequested)
{
var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
diff --git a/Emby.Server.Implementations/Logging/UnhandledExceptionWriter.cs b/Emby.Server.Implementations/Logging/UnhandledExceptionWriter.cs
index 5183f3a0b..7104935e1 100644
--- a/Emby.Server.Implementations/Logging/UnhandledExceptionWriter.cs
+++ b/Emby.Server.Implementations/Logging/UnhandledExceptionWriter.cs
@@ -29,15 +29,17 @@ namespace Emby.Server.Implementations.Logging
_logManager.Flush();
var path = Path.Combine(_appPaths.LogDirectoryPath, "unhandled_" + Guid.NewGuid() + ".txt");
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
var builder = LogHelper.GetLogMessage(ex);
// Write to console just in case file logging fails
_console.WriteLine("UnhandledException");
- _console.WriteLine(builder.ToString());
- _fileSystem.WriteAllText(path, builder.ToString());
+ var logMessage = builder.ToString();
+ _console.WriteLine(logMessage);
+
+ _fileSystem.WriteAllText(path, logMessage);
}
}
}
diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
index 204e04061..884a001f0 100644
--- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -138,7 +138,7 @@ namespace Emby.Server.Implementations.MediaEncoder
var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
var container = video.Container;
diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
index 386da73c6..18042b587 100644
--- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs
+++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
@@ -201,7 +201,8 @@ namespace Emby.Server.Implementations.Playlists
_providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
{
ForceSave = true
- });
+
+ }, RefreshPriority.High);
}
public async Task RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds)
@@ -228,7 +229,8 @@ namespace Emby.Server.Implementations.Playlists
_providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
{
ForceSave = true
- });
+
+ }, RefreshPriority.High);
}
public async Task MoveItem(string playlistId, string entryId, int newIndex)
diff --git a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs
index 5f37025e2..d1c70ba1d 100644
--- a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs
@@ -136,7 +136,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
{
previouslyFailedImages.Add(key);
- var parentPath = Path.GetDirectoryName(failHistoryPath);
+ var parentPath = _fileSystem.GetDirectoryName(failHistoryPath);
_fileSystem.CreateDirectory(parentPath);
diff --git a/Emby.Server.Implementations/Security/MBLicenseFile.cs b/Emby.Server.Implementations/Security/MBLicenseFile.cs
index c791d6a52..dc0e8b161 100644
--- a/Emby.Server.Implementations/Security/MBLicenseFile.cs
+++ b/Emby.Server.Implementations/Security/MBLicenseFile.cs
@@ -193,7 +193,7 @@ namespace Emby.Server.Implementations.Security
}
var licenseFile = Filename;
- _fileSystem.CreateDirectory(Path.GetDirectoryName(licenseFile));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(licenseFile));
lock (_fileLock)
{
_fileSystem.WriteAllLines(licenseFile, lines);
diff --git a/Emby.Server.Implementations/Session/HttpSessionController.cs b/Emby.Server.Implementations/Session/HttpSessionController.cs
index cea5d9b40..2acc3902f 100644
--- a/Emby.Server.Implementations/Session/HttpSessionController.cs
+++ b/Emby.Server.Implementations/Session/HttpSessionController.cs
@@ -129,7 +129,7 @@ namespace Emby.Server.Implementations.Session
public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
{
- return Task.FromResult(true);
+ return SendMessage("LibraryChanged", info, cancellationToken);
}
public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index 0a2312735..de00cf239 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -715,7 +715,8 @@ namespace Emby.Server.Implementations.Session
ClientName = session.Client,
DeviceId = session.DeviceId,
IsPaused = info.IsPaused,
- PlaySessionId = info.PlaySessionId
+ PlaySessionId = info.PlaySessionId,
+ IsAutomated = isAutomated
}, _logger);
diff --git a/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs b/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs
index b315d33c3..b441a29c1 100644
--- a/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs
+++ b/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs
@@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.Sorting
{
var hasSeries = item as IHasSeries;
- return hasSeries != null ? hasSeries.SeriesSortName : null;
+ return hasSeries != null ? hasSeries.FindSeriesSortName() : null;
}
/// <summary>
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index 840c7ce0d..57019cc4e 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/Emby.Server.Implementations/Updates/InstallationManager.cs
@@ -250,7 +250,7 @@ namespace Emby.Server.Implementations.Updates
}).ConfigureAwait(false);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(PackageCachePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(PackageCachePath));
_fileSystem.CopyFile(tempFile, PackageCachePath, true);
_lastPackageUpdateTime = DateTime.UtcNow;
@@ -627,7 +627,7 @@ namespace Emby.Server.Implementations.Updates
// Success - move it to the real target
try
{
- _fileSystem.CreateDirectory(Path.GetDirectoryName(target));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(target));
_fileSystem.CopyFile(tempFile, target, true);
//If it is an archive - write out a version file so we know what it is
if (isArchive)
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index a59ab33a9..53e474982 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -633,7 +633,7 @@ namespace MediaBrowser.Api
/// <param name="outputFilePath">The output file path.</param>
private void DeleteHlsPartialStreamFiles(string outputFilePath)
{
- var directory = Path.GetDirectoryName(outputFilePath);
+ var directory = _fileSystem.GetDirectoryName(outputFilePath);
var name = Path.GetFileNameWithoutExtension(outputFilePath);
var filesToDelete = _fileSystem.GetFilePaths(directory)
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index 1f21a1dd1..a802e56af 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -66,7 +66,7 @@ namespace MediaBrowser.Api
return ResultFactory.GetOptimizedResult(Request, result);
}
- protected void AssertCanUpdateUser(IAuthorizationContext authContext, IUserManager userManager, string userId)
+ protected void AssertCanUpdateUser(IAuthorizationContext authContext, IUserManager userManager, string userId, bool restrictUserPreferences)
{
var auth = authContext.GetAuthorizationInfo(Request);
@@ -80,7 +80,7 @@ namespace MediaBrowser.Api
throw new SecurityException("Unauthorized access.");
}
}
- else
+ else if (restrictUserPreferences)
{
if (!authenticatedUser.Policy.EnableUserPreferenceAccess)
{
diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs
index 1eeb92530..bce1e6682 100644
--- a/MediaBrowser.Api/ChannelService.cs
+++ b/MediaBrowser.Api/ChannelService.cs
@@ -98,7 +98,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string SortBy { get; set; }
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
/// <summary>
@@ -145,7 +145,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Filters { get; set; }
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
[ApiMember(Name = "ChannelIds", Description = "Optional. Specify one or more channel id's, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs
index bab538c91..c4cb0cb1d 100644
--- a/MediaBrowser.Api/EnvironmentService.cs
+++ b/MediaBrowser.Api/EnvironmentService.cs
@@ -278,7 +278,7 @@ namespace MediaBrowser.Api
public object Get(GetParentPath request)
{
- var parent = Path.GetDirectoryName(request.Path);
+ var parent = _fileSystem.GetDirectoryName(request.Path);
if (string.IsNullOrEmpty(parent))
{
diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs
index c4cfd7307..2c8fc2d61 100644
--- a/MediaBrowser.Api/Images/ImageByNameService.cs
+++ b/MediaBrowser.Api/Images/ImageByNameService.cs
@@ -160,7 +160,7 @@ namespace MediaBrowser.Api.Images
private string GetThemeName(string path, string rootImagePath)
{
- var parentName = Path.GetDirectoryName(path);
+ var parentName = _fileSystem.GetDirectoryName(path);
if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase))
{
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index 392654aa2..9f144c8e4 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -427,7 +427,7 @@ namespace MediaBrowser.Api.Images
public void Post(PostUserImage request)
{
var userId = GetPathValue(1);
- AssertCanUpdateUser(_authContext, _userManager, userId);
+ AssertCanUpdateUser(_authContext, _userManager, userId, true);
request.Type = (ImageType)Enum.Parse(typeof(ImageType), GetPathValue(3), true);
@@ -462,7 +462,7 @@ namespace MediaBrowser.Api.Images
public void Delete(DeleteUserImage request)
{
var userId = request.Id;
- AssertCanUpdateUser(_authContext, _userManager, userId);
+ AssertCanUpdateUser(_authContext, _userManager, userId, true);
var item = _userManager.GetUserById(userId);
diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs
index d7ccf8f6d..ebd8b8951 100644
--- a/MediaBrowser.Api/Images/RemoteImageService.cs
+++ b/MediaBrowser.Api/Images/RemoteImageService.cs
@@ -278,7 +278,7 @@ namespace MediaBrowser.Api.Images
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath));
using (var stream = result.Content)
{
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
@@ -287,7 +287,7 @@ namespace MediaBrowser.Api.Images
}
}
- _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath));
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
}
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs
index b5c51bfef..a454642a4 100644
--- a/MediaBrowser.Api/ItemLookupService.cs
+++ b/MediaBrowser.Api/ItemLookupService.cs
@@ -299,7 +299,7 @@ namespace MediaBrowser.Api
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(fullCachePath));
using (var stream = result.Content)
{
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
@@ -308,7 +308,7 @@ namespace MediaBrowser.Api
}
}
- _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(pointerCachePath));
_fileSystem.WriteAllText(pointerCachePath, fullCachePath);
}
diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs
index 81547637e..bca292241 100644
--- a/MediaBrowser.Api/ItemRefreshService.cs
+++ b/MediaBrowser.Api/ItemRefreshService.cs
@@ -62,14 +62,7 @@ namespace MediaBrowser.Api
var options = GetRefreshOptions(request);
- if (item is Folder)
- {
- _providerManager.QueueRefresh(item.Id, options);
- }
- else
- {
- _providerManager.RefreshFullItem(item, options, CancellationToken.None);
- }
+ _providerManager.QueueRefresh(item.Id, options, RefreshPriority.High);
}
private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request)
diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs
index 686a3a296..29530688c 100644
--- a/MediaBrowser.Api/ItemUpdateService.cs
+++ b/MediaBrowser.Api/ItemUpdateService.cs
@@ -240,7 +240,6 @@ namespace MediaBrowser.Api
item.OriginalTitle = string.IsNullOrWhiteSpace(request.OriginalTitle) ? null : request.OriginalTitle;
item.CriticRating = request.CriticRating;
- item.CriticRatingSummary = request.CriticRatingSummary;
item.DisplayMediaType = request.DisplayMediaType;
item.CommunityRating = request.CommunityRating;
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 2d8744f70..9fcdb4be5 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -98,7 +98,7 @@ namespace MediaBrowser.Api.LiveTv
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
[ApiMember(Name = "AddCurrentProgram", Description = "Optional. Adds current program info to each channel", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -189,7 +189,7 @@ namespace MediaBrowser.Api.LiveTv
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
public bool EnableTotalRecordCount { get; set; }
@@ -251,7 +251,7 @@ namespace MediaBrowser.Api.LiveTv
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
public bool EnableTotalRecordCount { get; set; }
@@ -399,7 +399,7 @@ namespace MediaBrowser.Api.LiveTv
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
public GetPrograms()
@@ -459,7 +459,7 @@ namespace MediaBrowser.Api.LiveTv
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
[ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 699c4bbb2..daec00e10 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -198,7 +198,7 @@ namespace MediaBrowser.Api.Playback
CancellationTokenSource cancellationTokenSource,
string workingDirectory = null)
{
- FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(outputPath));
await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
@@ -263,7 +263,7 @@ namespace MediaBrowser.Api.Playback
}
var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt");
- FileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(logFilePath));
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
@@ -315,8 +315,6 @@ namespace MediaBrowser.Api.Playback
StartThrottler(state, transcodingJob);
}
- ReportUsage(state);
-
return transcodingJob;
}
@@ -677,7 +675,8 @@ namespace MediaBrowser.Api.Playback
{
Request = request,
RequestedUrl = url,
- UserAgent = Request.UserAgent
+ UserAgent = Request.UserAgent,
+ EnableDlnaHeaders = !string.IsNullOrWhiteSpace(request.Params)
};
var auth = AuthorizationContext.GetAuthorizationInfo(Request);
@@ -720,6 +719,13 @@ namespace MediaBrowser.Api.Playback
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
+ //var primaryImage = item.GetImageInfo(ImageType.Primary, 0) ??
+ // item.Parents.Select(i => i.GetImageInfo(ImageType.Primary, 0)).FirstOrDefault(i => i != null);
+ //if (primaryImage != null)
+ //{
+ // state.AlbumCoverPath = primaryImage.Path;
+ //}
+
MediaSourceInfo mediaSource = null;
if (string.IsNullOrWhiteSpace(request.LiveStreamId))
{
@@ -903,123 +909,6 @@ namespace MediaBrowser.Api.Playback
}
}
- private async void ReportUsage(StreamState state)
- {
- try
- {
- await ReportUsageInternal(state).ConfigureAwait(false);
- }
- catch
- {
-
- }
- }
-
- private Task ReportUsageInternal(StreamState state)
- {
- if (!ServerConfigurationManager.Configuration.EnableAnonymousUsageReporting)
- {
- return Task.FromResult(true);
- }
-
- if (!MediaEncoder.IsDefaultEncoderPath)
- {
- return Task.FromResult(true);
- }
- return Task.FromResult(true);
-
- //var dict = new Dictionary<string, string>();
-
- //var outputAudio = GetAudioEncoder(state);
- //if (!string.IsNullOrWhiteSpace(outputAudio))
- //{
- // dict["outputAudio"] = outputAudio;
- //}
-
- //var outputVideo = GetVideoEncoder(state);
- //if (!string.IsNullOrWhiteSpace(outputVideo))
- //{
- // dict["outputVideo"] = outputVideo;
- //}
-
- //if (ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase) &&
- // ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
- //{
- // return Task.FromResult(true);
- //}
-
- //dict["id"] = AppHost.SystemId;
- //dict["type"] = state.VideoRequest == null ? "Audio" : "Video";
-
- //var audioStream = state.AudioStream;
- //if (audioStream != null && !string.IsNullOrWhiteSpace(audioStream.Codec))
- //{
- // dict["inputAudio"] = audioStream.Codec;
- //}
-
- //var videoStream = state.VideoStream;
- //if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
- //{
- // dict["inputVideo"] = videoStream.Codec;
- //}
-
- //var cert = GetType().Assembly.GetModules().First().GetSignerCertificate();
- //if (cert != null)
- //{
- // dict["assemblySig"] = cert.GetCertHashString();
- // dict["certSubject"] = cert.Subject ?? string.Empty;
- // dict["certIssuer"] = cert.Issuer ?? string.Empty;
- //}
- //else
- //{
- // return Task.FromResult(true);
- //}
-
- //if (state.SupportedAudioCodecs.Count > 0)
- //{
- // dict["supportedAudioCodecs"] = string.Join(",", state.SupportedAudioCodecs.ToArray());
- //}
-
- //var auth = AuthorizationContext.GetAuthorizationInfo(Request);
-
- //dict["appName"] = auth.Client ?? string.Empty;
- //dict["appVersion"] = auth.Version ?? string.Empty;
- //dict["device"] = auth.Device ?? string.Empty;
- //dict["deviceId"] = auth.DeviceId ?? string.Empty;
- //dict["context"] = "streaming";
-
- ////Logger.Info(JsonSerializer.SerializeToString(dict));
- //if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputAudio ?? string.Empty, StringComparer.OrdinalIgnoreCase))
- //{
- // var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
- // list.Add(outputAudio);
- // ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
- //}
-
- //if (!ServerConfigurationManager.Configuration.CodecsUsed.Contains(outputVideo ?? string.Empty, StringComparer.OrdinalIgnoreCase))
- //{
- // var list = ServerConfigurationManager.Configuration.CodecsUsed.ToList();
- // list.Add(outputVideo);
- // ServerConfigurationManager.Configuration.CodecsUsed = list.ToArray();
- //}
-
- //ServerConfigurationManager.SaveConfiguration();
-
- ////Logger.Info(JsonSerializer.SerializeToString(dict));
- //var options = new HttpRequestOptions()
- //{
- // Url = "https://mb3admin.com/admin/service/transcoding/report",
- // CancellationToken = CancellationToken.None,
- // LogRequest = false,
- // LogErrors = false,
- // BufferContent = false
- //};
- //options.RequestContent = JsonSerializer.SerializeToString(dict);
- //options.RequestContentType = "application/json";
-
- //return HttpClient.Post(options);
- }
-
/// <summary>
/// Adds the dlna headers.
/// </summary>
@@ -1029,6 +918,11 @@ namespace MediaBrowser.Api.Playback
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
protected void AddDlnaHeaders(StreamState state, IDictionary<string, string> responseHeaders, bool isStaticallyStreamed)
{
+ if (!state.EnableDlnaHeaders)
+ {
+ return;
+ }
+
var profile = state.DeviceProfile;
var transferMode = GetHeader("transferMode.dlna.org");
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 53813860a..fcf57cebe 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -13,10 +13,7 @@ using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.IO;
namespace MediaBrowser.Api.Playback.Hls
{
@@ -271,7 +268,7 @@ namespace MediaBrowser.Api.Playback.Hls
var useGenericSegmenter = true;
if (useGenericSegmenter)
{
- var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
+ var outputTsArg = Path.Combine(FileSystem.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
var timeDeltaParam = String.Empty;
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 038d76245..0fe1e533d 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -89,6 +89,7 @@ namespace MediaBrowser.Api.Playback.Hls
public string SegmentId { get; set; }
}
+ [Authenticated]
public class DynamicHlsService : BaseHlsService
{
@@ -378,7 +379,7 @@ namespace MediaBrowser.Api.Playback.Hls
private static FileSystemMetadata GetLastTranscodingFile(string playlist, string segmentExtension, IFileSystem fileSystem)
{
- var folder = Path.GetDirectoryName(playlist);
+ var folder = fileSystem.GetDirectoryName(playlist);
var filePrefix = Path.GetFileNameWithoutExtension(playlist) ?? string.Empty;
@@ -415,7 +416,7 @@ namespace MediaBrowser.Api.Playback.Hls
private string GetSegmentPath(StreamState state, string playlist, int index)
{
- var folder = Path.GetDirectoryName(playlist);
+ var folder = FileSystem.GetDirectoryName(playlist);
var filename = Path.GetFileNameWithoutExtension(playlist);
@@ -807,7 +808,7 @@ namespace MediaBrowser.Api.Playback.Hls
if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
{
- return "-codec:a:0 copy";
+ return "-codec:a:0 copy -copypriorss:a:0 0";
}
var args = "-codec:a:0 " + codec;
@@ -925,7 +926,7 @@ namespace MediaBrowser.Api.Playback.Hls
if (useGenericSegmenter)
{
- var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
+ var outputTsArg = Path.Combine(FileSystem.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request);
var timeDeltaParam = String.Empty;
diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
index ae049a83a..0ff52e63f 100644
--- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
+++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
@@ -15,6 +15,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// <summary>
/// Class GetHlsAudioSegment
/// </summary>
+ // Can't require authentication just yet due to seeing some requests come from Chrome without full query string
+ //[Authenticated]
[Route("/Audio/{Id}/hls/{SegmentId}/stream.mp3", "GET")]
[Route("/Audio/{Id}/hls/{SegmentId}/stream.aac", "GET")]
public class GetHlsAudioSegmentLegacy
@@ -38,6 +40,7 @@ namespace MediaBrowser.Api.Playback.Hls
/// Class GetHlsVideoSegment
/// </summary>
[Route("/Videos/{Id}/hls/{PlaylistId}/stream.m3u8", "GET")]
+ [Authenticated]
public class GetHlsPlaylistLegacy
{
// TODO: Deprecate with new iOS app
@@ -52,6 +55,7 @@ namespace MediaBrowser.Api.Playback.Hls
}
[Route("/Videos/ActiveEncodings", "DELETE")]
+ [Authenticated]
public class StopEncodingProcess
{
[ApiMember(Name = "DeviceId", Description = "The device id of the client requesting. Used to stop encoding processes when needed.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
@@ -64,6 +68,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// <summary>
/// Class GetHlsVideoSegment
/// </summary>
+ // Can't require authentication just yet due to seeing some requests come from Chrome without full query string
+ //[Authenticated]
[Route("/Videos/{Id}/hls/{PlaylistId}/{SegmentId}.{SegmentContainer}", "GET")]
public class GetHlsVideoSegmentLegacy : VideoStreamRequest
{
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index a813d7a87..22c6202e4 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -20,6 +20,7 @@ namespace MediaBrowser.Api.Playback.Hls
/// <summary>
/// Class VideoHlsService
/// </summary>
+ [Authenticated]
public class VideoHlsService : BaseHlsService
{
public object Get(GetLiveHlsStream request)
diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
index a64523e40..f0386d5ba 100644
--- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
@@ -59,42 +59,7 @@ namespace MediaBrowser.Api.Playback.Progressive
{
var encodingOptions = ApiEntryPoint.Instance.GetEncodingOptions();
- var audioTranscodeParams = new List<string>();
-
- var bitrate = state.OutputAudioBitrate;
-
- if (bitrate.HasValue)
- {
- audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(UsCulture));
- }
-
- if (state.OutputAudioChannels.HasValue)
- {
- audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(UsCulture));
- }
-
- // opus will fail on 44100
- if (!string.Equals(state.OutputAudioCodec, "opus", global::System.StringComparison.OrdinalIgnoreCase))
- {
- if (state.OutputAudioSampleRate.HasValue)
- {
- audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture));
- }
- }
-
- const string vn = " -vn";
-
- var threads = EncodingHelper.GetNumberOfThreads(state, encodingOptions, false);
-
- var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions);
-
- return string.Format("{0} {1} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1 -y \"{5}\"",
- inputModifier,
- EncodingHelper.GetInputArgument(state, encodingOptions),
- threads,
- vn,
- string.Join(" ", audioTranscodeParams.ToArray()),
- outputPath).Trim();
+ return EncodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath);
}
public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor)
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index 8394e016c..c36a27690 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -62,6 +62,8 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <summary>
/// Class VideoService
/// </summary>
+ // TODO: In order to autheneticate this in the future, Dlna playback will require updating
+ //[Authenticated]
public class VideoService : BaseProgressiveStreamingService
{
public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, authorizationContext, imageProcessor)
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index 7f146466d..4b1687d68 100644
--- a/MediaBrowser.Api/Playback/StreamState.cs
+++ b/MediaBrowser.Api/Playback/StreamState.cs
@@ -138,6 +138,8 @@ namespace MediaBrowser.Api.Playback
return MimeTypes.GetMimeType(outputPath);
}
+ public bool EnableDlnaHeaders { get; set; }
+
public void Dispose()
{
DisposeTranscodingThrottler();
diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs
index bb2bc449b..9f37bb70a 100644
--- a/MediaBrowser.Api/PlaylistService.cs
+++ b/MediaBrowser.Api/PlaylistService.cs
@@ -102,7 +102,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
diff --git a/MediaBrowser.Api/Reports/ReportsService.cs b/MediaBrowser.Api/Reports/ReportsService.cs
index 5e13c1653..9490c301d 100644
--- a/MediaBrowser.Api/Reports/ReportsService.cs
+++ b/MediaBrowser.Api/Reports/ReportsService.cs
@@ -300,11 +300,6 @@ namespace MediaBrowser.Api.Reports
}
}
- if (!string.IsNullOrEmpty(request.LocationTypes))
- {
- query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
- }
-
// Min official rating
if (!string.IsNullOrWhiteSpace(request.MinOfficialRating))
{
diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs
index d6fa4030d..3df815cda 100644
--- a/MediaBrowser.Api/SearchService.cs
+++ b/MediaBrowser.Api/SearchService.cs
@@ -9,6 +9,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Search;
using System.Linq;
using System.Threading.Tasks;
+using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Services;
namespace MediaBrowser.Api
@@ -66,6 +67,23 @@ namespace MediaBrowser.Api
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string IncludeItemTypes { get; set; }
+ public string ParentId { get; set; }
+
+ [ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
+ public bool? IsMovie { get; set; }
+
+ [ApiMember(Name = "IsSeries", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
+ public bool? IsSeries { get; set; }
+
+ [ApiMember(Name = "IsNews", Description = "Optional filter for news.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
+ public bool? IsNews { get; set; }
+
+ [ApiMember(Name = "IsKids", Description = "Optional filter for kids.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
+ public bool? IsKids { get; set; }
+
+ [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
+ public bool? IsSports { get; set; }
+
public GetSearchHints()
{
IncludeArtists = true;
@@ -135,7 +153,14 @@ namespace MediaBrowser.Api
IncludeStudios = request.IncludeStudios,
StartIndex = request.StartIndex,
UserId = request.UserId,
- IncludeItemTypes = (request.IncludeItemTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray()
+ IncludeItemTypes = (request.IncludeItemTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(),
+ ParentId = request.ParentId,
+
+ IsKids = request.IsKids,
+ IsMovie = request.IsMovie,
+ IsNews = request.IsNews,
+ IsSeries = request.IsSeries,
+ IsSports = request.IsSports
}).ConfigureAwait(false);
@@ -167,11 +192,11 @@ namespace MediaBrowser.Api
MatchedTerm = hintInfo.MatchedTerm,
DisplayMediaType = item.DisplayMediaType,
RunTimeTicks = item.RunTimeTicks,
- ProductionYear = item.ProductionYear
+ ProductionYear = item.ProductionYear,
+ ChannelId = item.ChannelId,
+ EndDate = item.EndDate
};
- result.ChannelId = item.ChannelId;
-
var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
if (primaryImageTag != null)
@@ -183,12 +208,27 @@ namespace MediaBrowser.Api
SetThumbImageInfo(result, item);
SetBackdropImageInfo(result, item);
+ var program = item as LiveTvProgram;
+ if (program != null)
+ {
+ result.StartDate = program.StartDate;
+ }
+
var hasSeries = item as IHasSeries;
if (hasSeries != null)
{
result.Series = hasSeries.SeriesName;
}
+ var series = item as Series;
+ if (series != null)
+ {
+ if (series.Status.HasValue)
+ {
+ result.Status = series.Status.Value.ToString();
+ }
+ }
+
var album = item as MusicAlbum;
if (album != null)
diff --git a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
index b90a71852..e133a88a1 100644
--- a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
+++ b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
@@ -58,7 +58,7 @@ namespace MediaBrowser.Api.Session
void _sessionManager_PlaybackProgress(object sender, PlaybackProgressEventArgs e)
{
- SendData(false);
+ SendData(!e.IsAutomated);
}
void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e)
diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs
index 892c9f698..5463ae982 100644
--- a/MediaBrowser.Api/SimilarItemsHelper.cs
+++ b/MediaBrowser.Api/SimilarItemsHelper.cs
@@ -61,7 +61,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
}
diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs
index 5a1074b7b..7e13512aa 100644
--- a/MediaBrowser.Api/StartupWizardService.cs
+++ b/MediaBrowser.Api/StartupWizardService.cs
@@ -95,12 +95,12 @@ namespace MediaBrowser.Api
config.EnableStandaloneMusicKeys = true;
config.EnableCaseSensitiveItemIds = true;
config.SkipDeserializationForBasicTypes = true;
- config.SkipDeserializationForPrograms = true;
config.SkipDeserializationForAudio = true;
config.EnableSeriesPresentationUniqueKey = true;
config.EnableLocalizedGuids = true;
config.EnableSimpleArtistDetection = true;
config.EnableNormalizedItemByNameIds = true;
+ config.DisableLiveTvChannelUserDataName = true;
}
public void Post(UpdateStartupConfiguration request)
diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
index 47d442e79..798004a5e 100644
--- a/MediaBrowser.Api/Subtitles/SubtitleService.cs
+++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs
@@ -288,7 +288,7 @@ namespace MediaBrowser.Api.Subtitles
await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
.ConfigureAwait(false);
- _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem));
+ _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem), RefreshPriority.High);
}
catch (Exception ex)
{
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index 126f1c753..4b279031e 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -48,7 +48,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
[ApiMember(Name = "SeriesId", Description = "Optional. Filter by series id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -108,7 +108,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
/// <summary>
@@ -150,7 +150,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -215,7 +215,7 @@ namespace MediaBrowser.Api
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
[ApiMember(Name = "Id", Description = "The series id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -497,7 +497,7 @@ namespace MediaBrowser.Api
}
else
{
- episodes = series.GetSeasonEpisodes(season, user);
+ episodes = season.GetEpisodes(user);
}
}
else
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
index 1acbce6db..55c23841c 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
@@ -146,7 +146,7 @@ namespace MediaBrowser.Api.UserLibrary
/// Fields to return within the items, in addition to basic information
/// </summary>
/// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index 5d267d059..f8580d328 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -328,7 +328,15 @@ namespace MediaBrowser.Api.UserLibrary
if (!string.IsNullOrEmpty(request.LocationTypes))
{
- query.LocationTypes = request.LocationTypes.Split(',').Select(d => (LocationType)Enum.Parse(typeof(LocationType), d, true)).ToArray();
+ var requestedLocationTypes =
+ request.LocationTypes.Split(',')
+ .Select(d => (LocationType) Enum.Parse(typeof (LocationType), d, true))
+ .ToList();
+
+ if (requestedLocationTypes.Count > 0 && requestedLocationTypes.Count < 4)
+ {
+ query.IsVirtualItem = requestedLocationTypes.Contains(LocationType.Virtual);
+ }
}
// Min official rating
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index 32f3a1f00..b1f196f15 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -225,7 +225,7 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ParentId { get; set; }
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Fields { get; set; }
[ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index fde03e1f2..49b7f6c15 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -444,7 +444,7 @@ namespace MediaBrowser.Api
public async Task PostAsync(UpdateUserPassword request)
{
- AssertCanUpdateUser(_authContext, _userManager, request.Id);
+ AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
var user = _userManager.GetUserById(request.Id);
@@ -482,7 +482,7 @@ namespace MediaBrowser.Api
public async Task PostAsync(UpdateUserEasyPassword request)
{
- AssertCanUpdateUser(_authContext, _userManager, request.Id);
+ AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
var user = _userManager.GetUserById(request.Id);
@@ -518,7 +518,7 @@ namespace MediaBrowser.Api
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
var id = GetPathValue(1);
- AssertCanUpdateUser(_authContext, _userManager, id);
+ AssertCanUpdateUser(_authContext, _userManager, id, false);
var dtoUser = request;
@@ -568,7 +568,7 @@ namespace MediaBrowser.Api
public void Post(UpdateUserConfiguration request)
{
- AssertCanUpdateUser(_authContext, _userManager, request.Id);
+ AssertCanUpdateUser(_authContext, _userManager, request.Id, false);
var task = _userManager.UpdateConfiguration(request.Id, request);
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 59b5a3869..92d8d95bc 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -9,7 +9,6 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Channels;
using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Controller.Entities.Audio
@@ -24,8 +23,6 @@ namespace MediaBrowser.Controller.Entities.Audio
IHasLookupInfo<SongInfo>,
IHasMediaSources
{
- public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
-
/// <summary>
/// Gets or sets the artist.
/// </summary>
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
index e26e0dfce..2f99e530e 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
@@ -112,7 +112,7 @@ namespace MediaBrowser.Controller.Entities.Audio
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
{
- query.Genres = new[] { Name };
+ query.GenreIds = new[] { Id.ToString("N") };
query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
return LibraryManager.GetItemList(query);
diff --git a/MediaBrowser.Controller/Entities/AudioBook.cs b/MediaBrowser.Controller/Entities/AudioBook.cs
index 8b1c338f1..1bdcfb881 100644
--- a/MediaBrowser.Controller/Entities/AudioBook.cs
+++ b/MediaBrowser.Controller/Entities/AudioBook.cs
@@ -31,12 +31,10 @@ namespace MediaBrowser.Controller.Entities
public string SeriesName { get; set; }
[IgnoreDataMember]
public Guid? SeriesId { get; set; }
- [IgnoreDataMember]
- public string SeriesSortName { get; set; }
public string FindSeriesSortName()
{
- return SeriesSortName;
+ return SeriesName;
}
public string FindSeriesName()
{
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index c8ea4c506..999f6db3f 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -84,6 +84,7 @@ namespace MediaBrowser.Controller.Entities
public long? Size { get; set; }
public string Container { get; set; }
+
[IgnoreDataMember]
public string Tagline { get; set; }
@@ -288,7 +289,7 @@ namespace MediaBrowser.Controller.Entities
return Path;
}
- return System.IO.Path.GetDirectoryName(Path);
+ return FileSystem.GetDirectoryName(Path);
}
}
@@ -835,20 +836,6 @@ namespace MediaBrowser.Controller.Entities
public float? CriticRating { get; set; }
/// <summary>
- /// Gets or sets the critic rating summary.
- /// </summary>
- /// <value>The critic rating summary.</value>
- [IgnoreDataMember]
- public string CriticRatingSummary { get; set; }
-
- /// <summary>
- /// Gets or sets the official rating description.
- /// </summary>
- /// <value>The official rating description.</value>
- [IgnoreDataMember]
- public string OfficialRatingDescription { get; set; }
-
- /// <summary>
/// Gets or sets the custom rating.
/// </summary>
/// <value>The custom rating.</value>
@@ -1824,7 +1811,7 @@ namespace MediaBrowser.Controller.Entities
/// <returns>Task.</returns>
public virtual Task ChangedExternally()
{
- ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions(FileSystem));
+ ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions(FileSystem), RefreshPriority.High);
return Task.FromResult(true);
}
@@ -1924,7 +1911,7 @@ namespace MediaBrowser.Controller.Entities
{
var allFiles = ImageInfos
.Where(i => i.IsLocalFile)
- .Select(i => System.IO.Path.GetDirectoryName(i.Path))
+ .Select(i => FileSystem.GetDirectoryName(i.Path))
.Distinct(StringComparer.OrdinalIgnoreCase)
.SelectMany(directoryService.GetFilePaths)
.ToList();
@@ -2099,7 +2086,7 @@ namespace MediaBrowser.Controller.Entities
var extensions = new[] { ".nfo", ".xml", ".srt" }.ToList();
extensions.AddRange(SupportedImageExtensionsList);
- return FileSystem.GetFiles(System.IO.Path.GetDirectoryName(Path), extensions.ToArray(), false, false)
+ return FileSystem.GetFiles(FileSystem.GetDirectoryName(Path), extensions.ToArray(), false, false)
.Where(i => System.IO.Path.GetFileNameWithoutExtension(i.FullName).StartsWith(filename, StringComparison.OrdinalIgnoreCase))
.ToList();
}
@@ -2298,16 +2285,6 @@ namespace MediaBrowser.Controller.Entities
ownedItem.CustomRating = item.CustomRating;
newOptions.ForceSave = true;
}
- if (!string.Equals(item.CriticRatingSummary, ownedItem.CriticRatingSummary, StringComparison.Ordinal))
- {
- ownedItem.CriticRatingSummary = item.CriticRatingSummary;
- newOptions.ForceSave = true;
- }
- if (!string.Equals(item.OfficialRatingDescription, ownedItem.OfficialRatingDescription, StringComparison.Ordinal))
- {
- ownedItem.OfficialRatingDescription = item.OfficialRatingDescription;
- newOptions.ForceSave = true;
- }
}
return ownedItem.RefreshMetadata(newOptions, cancellationToken);
diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs
index a6da389f0..7cb242589 100644
--- a/MediaBrowser.Controller/Entities/Book.cs
+++ b/MediaBrowser.Controller/Entities/Book.cs
@@ -24,12 +24,10 @@ namespace MediaBrowser.Controller.Entities
public string SeriesName { get; set; }
[IgnoreDataMember]
public Guid? SeriesId { get; set; }
- [IgnoreDataMember]
- public string SeriesSortName { get; set; }
public string FindSeriesSortName()
{
- return SeriesSortName;
+ return SeriesName;
}
public string FindSeriesName()
{
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index 62ea21a79..24474ba55 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -213,7 +213,7 @@ namespace MediaBrowser.Controller.Entities
.SelectMany(c => c.LinkedChildren)
.ToList();
- var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer());
+ var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer(FileSystem));
LinkedChildren = linkedChildren;
@@ -332,13 +332,13 @@ namespace MediaBrowser.Controller.Entities
.OfType<Folder>()
.ToList();
- return PhysicalLocations.Where(i => !string.Equals(i, Path, StringComparison.OrdinalIgnoreCase)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id);
+ return PhysicalLocations.Where(i => !FileSystem.AreEqual(i, Path)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id);
}
private IEnumerable<Folder> GetPhysicalParents(string path, List<Folder> rootChildren)
{
var result = rootChildren
- .Where(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase))
+ .Where(i => FileSystem.AreEqual(i.Path, path))
.ToList();
if (result.Count == 0)
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 268fefbd3..edac27f99 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -640,7 +640,7 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- path = System.IO.Path.GetDirectoryName(path);
+ path = FileSystem.GetDirectoryName(path);
}
return allLibraryPaths.Any(i => ContainsPath(i, originalPath));
@@ -1206,11 +1206,17 @@ namespace MediaBrowser.Controller.Entities
return GetLinkedChildren();
}
- var locations = user.RootFolder
- .Children
+ if (LinkedChildren.Count == 0)
+ {
+ return new List<BaseItem>();
+ }
+
+ var allUserRootChildren = user.RootFolder.Children.OfType<Folder>().ToList();
+
+ var collectionFolderIds = allUserRootChildren
.OfType<CollectionFolder>()
.Where(i => i.IsVisible(user))
- .SelectMany(i => i.PhysicalLocations)
+ .Select(i => i.Id)
.ToList();
return LinkedChildren
@@ -1228,9 +1234,16 @@ namespace MediaBrowser.Controller.Entities
return null;
}
}
- else if (childLocationType == LocationType.FileSystem && !locations.Any(l => FileSystem.ContainsSubPath(l, child.Path)))
+ else if (childLocationType == LocationType.FileSystem)
{
- return null;
+ var itemCollectionFolderIds =
+ LibraryManager.GetCollectionFolders(child, allUserRootChildren)
+ .Select(f => f.Id).ToList();
+
+ if (!itemCollectionFolderIds.Any(collectionFolderIds.Contains))
+ {
+ return null;
+ }
}
}
@@ -1323,7 +1336,7 @@ namespace MediaBrowser.Controller.Entities
}
else { newShortcutLinks = new List<LinkedChild>(); }
- if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer()))
+ if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer(FileSystem)))
{
Logger.Info("Shortcut links have changed for {0}", Path);
diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs
index d19552c07..baefc9dfa 100644
--- a/MediaBrowser.Controller/Entities/Game.cs
+++ b/MediaBrowser.Controller/Entities/Game.cs
@@ -105,7 +105,7 @@ namespace MediaBrowser.Controller.Entities
return new[] {
new FileSystemMetadata
{
- FullName = System.IO.Path.GetDirectoryName(Path),
+ FullName = FileSystem.GetDirectoryName(Path),
IsDirectory = true
}
};
diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs
index 4187167b9..093b191b6 100644
--- a/MediaBrowser.Controller/Entities/GameGenre.cs
+++ b/MediaBrowser.Controller/Entities/GameGenre.cs
@@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.Entities
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
{
- query.Genres = new[] { Name };
+ query.GenreIds = new[] { Id.ToString("N") };
query.IncludeItemTypes = new[] { typeof(Game).Name };
return LibraryManager.GetItemList(query);
diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs
index 9769efdd0..6569a1e6c 100644
--- a/MediaBrowser.Controller/Entities/Genre.cs
+++ b/MediaBrowser.Controller/Entities/Genre.cs
@@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.Entities
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
{
- query.Genres = new[] { Name };
+ query.GenreIds = new[] { Id.ToString("N") };
query.ExcludeItemTypes = new[] { typeof(Game).Name, typeof(MusicVideo).Name, typeof(Audio.Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
return LibraryManager.GetItemList(query);
diff --git a/MediaBrowser.Controller/Entities/IHasSeries.cs b/MediaBrowser.Controller/Entities/IHasSeries.cs
index 203be93e8..20efdc2b8 100644
--- a/MediaBrowser.Controller/Entities/IHasSeries.cs
+++ b/MediaBrowser.Controller/Entities/IHasSeries.cs
@@ -11,7 +11,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The name of the series.</value>
string SeriesName { get; set; }
string FindSeriesName();
- string SeriesSortName { get; set; }
string FindSeriesSortName();
Guid? SeriesId { get; set; }
Guid? FindSeriesId();
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index ea4d60a44..092461c84 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -129,7 +129,6 @@ namespace MediaBrowser.Controller.Entities
public string[] AncestorIds { get; set; }
public string[] TopParentIds { get; set; }
- public LocationType[] LocationTypes { get; set; }
public string[] PresetViews { get; set; }
public SourceType[] SourceTypes { get; set; }
public SourceType[] ExcludeSourceTypes { get; set; }
@@ -176,7 +175,6 @@ namespace MediaBrowser.Controller.Entities
case ItemFields.DateCreated:
case ItemFields.SortName:
case ItemFields.Overview:
- case ItemFields.OfficialRatingDescription:
case ItemFields.HomePageUrl:
case ItemFields.VoteCount:
case ItemFields.DisplayMediaType:
@@ -187,7 +185,6 @@ namespace MediaBrowser.Controller.Entities
case ItemFields.OriginalTitle:
case ItemFields.Tags:
case ItemFields.DateLastMediaAdded:
- case ItemFields.CriticRatingSummary:
return fields.Count == 0 || fields.Contains(name);
default:
return true;
@@ -230,7 +227,6 @@ namespace MediaBrowser.Controller.Entities
TopParentIds = new string[] { };
ExcludeTags = new string[] { };
ExcludeInheritedTags = new string[] { };
- LocationTypes = new LocationType[] { };
PresetViews = new string[] { };
SourceTypes = new SourceType[] { };
ExcludeSourceTypes = new SourceType[] { };
diff --git a/MediaBrowser.Controller/Entities/LinkedChild.cs b/MediaBrowser.Controller/Entities/LinkedChild.cs
index 4d3c13c6e..6031a2448 100644
--- a/MediaBrowser.Controller/Entities/LinkedChild.cs
+++ b/MediaBrowser.Controller/Entities/LinkedChild.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Controller.Entities
@@ -40,11 +41,18 @@ namespace MediaBrowser.Controller.Entities
public class LinkedChildComparer : IEqualityComparer<LinkedChild>
{
+ private readonly IFileSystem _fileSystem;
+
+ public LinkedChildComparer(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
public bool Equals(LinkedChild x, LinkedChild y)
{
if (x.Type == y.Type)
{
- return string.Equals(x.Path, y.Path, StringComparison.OrdinalIgnoreCase);
+ return _fileSystem.AreEqual(x.Path, y.Path);
}
return false;
}
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index 030831717..3f733ce03 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -152,9 +152,7 @@ namespace MediaBrowser.Controller.Entities.Movies
var currentOfficialRating = OfficialRating;
// Gather all possible ratings
- var ratings = GetRecursiveChildren()
- .Concat(GetLinkedChildren())
- .Where(i => i is Movie || i is Series || i is MusicAlbum || i is Game)
+ var ratings = GetRecursiveChildren(i => i is Movie || i is Series || i is MusicAlbum || i is Game)
.Select(i => i.OfficialRating)
.Where(i => !string.IsNullOrEmpty(i))
.Distinct(StringComparer.OrdinalIgnoreCase)
@@ -205,7 +203,7 @@ namespace MediaBrowser.Controller.Entities.Movies
if (base.IsVisible(user))
{
- return GetChildren(user, true).Any();
+ return base.GetChildren(user, true).Any();
}
return false;
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index 31bf8d28b..c2f7a6168 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -57,13 +57,10 @@ namespace MediaBrowser.Controller.Entities.TV
/// <value>The index number.</value>
public int? IndexNumberEnd { get; set; }
- [IgnoreDataMember]
- public string SeriesSortName { get; set; }
-
public string FindSeriesSortName()
{
var series = Series;
- return series == null ? SeriesSortName : series.SortName;
+ return series == null ? SeriesName : series.SortName;
}
[IgnoreDataMember]
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs
index be268782d..ed04b5ddc 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -51,9 +51,6 @@ namespace MediaBrowser.Controller.Entities.TV
get { return SeriesId; }
}
- [IgnoreDataMember]
- public string SeriesSortName { get; set; }
-
public override double? GetDefaultPrimaryImageAspectRatio()
{
double value = 2;
@@ -65,7 +62,7 @@ namespace MediaBrowser.Controller.Entities.TV
public string FindSeriesSortName()
{
var series = Series;
- return series == null ? SeriesSortName : series.SortName;
+ return series == null ? SeriesName : series.SortName;
}
// Genre, Rating and Stuido will all be the same
@@ -125,7 +122,7 @@ namespace MediaBrowser.Controller.Entities.TV
return series.Path;
}
- return System.IO.Path.GetDirectoryName(Path);
+ return FileSystem.GetDirectoryName(Path);
}
}
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index f879d0fd8..8da069f62 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -586,7 +586,7 @@ namespace MediaBrowser.Controller.Entities
{
query.Recursive = true;
query.ParentId = queryParent.Id;
- query.Genres = new[] { displayParent.Name };
+ query.GenreIds = new[] { displayParent.Id.ToString("N") };
query.SetUser(user);
query.IncludeItemTypes = new[] { typeof(Movie).Name };
@@ -729,7 +729,7 @@ namespace MediaBrowser.Controller.Entities
{
query.Recursive = true;
query.ParentId = queryParent.Id;
- query.Genres = new[] { displayParent.Name };
+ query.GenreIds = new[] { displayParent.Id.ToString("N") };
query.SetUser(user);
query.IncludeItemTypes = new[] { typeof(Series).Name };
@@ -905,6 +905,11 @@ namespace MediaBrowser.Controller.Entities
return false;
}
+ if (request.GenreIds.Length > 0)
+ {
+ return false;
+ }
+
if (request.HasImdbId.HasValue)
{
return false;
@@ -1768,26 +1773,6 @@ namespace MediaBrowser.Controller.Entities
return new List<Folder> { parent };
}
- private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, IEnumerable<string> viewTypes)
- {
- if (parent == null || parent is UserView)
- {
- if (user == null)
- {
- return GetMediaFolders(null, viewTypes).SelectMany(i => i.GetRecursiveChildren());
- }
-
- return GetMediaFolders(user, viewTypes).SelectMany(i => i.GetRecursiveChildren(user));
- }
-
- if (user == null)
- {
- return parent.GetRecursiveChildren();
- }
-
- return parent.GetRecursiveChildren(user);
- }
-
private async Task<QueryResult<BaseItem>> GetLiveTvView(Folder queryParent, User user, InternalItemsQuery query)
{
if (query.Recursive)
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index 0618fc489..90aa3690a 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -33,7 +33,6 @@ namespace MediaBrowser.Controller.Entities
public List<string> AdditionalParts { get; set; }
public List<string> LocalAlternateVersions { get; set; }
public List<LinkedChild> LinkedAlternateVersions { get; set; }
- public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
[IgnoreDataMember]
public override bool SupportsPlayedStatus
@@ -158,7 +157,6 @@ namespace MediaBrowser.Controller.Entities
PlayableStreamFileNames = new List<string>();
AdditionalParts = new List<string>();
LocalAlternateVersions = new List<string>();
- Tags = new List<string>();
SubtitleFiles = new List<string>();
LinkedAlternateVersions = new List<LinkedChild>();
}
@@ -313,7 +311,7 @@ namespace MediaBrowser.Controller.Entities
{
if (IsStacked)
{
- return System.IO.Path.GetDirectoryName(Path);
+ return FileSystem.GetDirectoryName(Path);
}
if (!IsPlaceHolder)
@@ -591,41 +589,46 @@ namespace MediaBrowser.Controller.Entities
.ToList();
}
- private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video i, MediaSourceType type)
+ private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video media, MediaSourceType type)
{
- var mediaStreams = MediaSourceManager.GetMediaStreams(i.Id)
+ if (media == null)
+ {
+ throw new ArgumentNullException("media");
+ }
+
+ var mediaStreams = MediaSourceManager.GetMediaStreams(media.Id)
.ToList();
- var locationType = i.LocationType;
+ var locationType = media.LocationType;
var info = new MediaSourceInfo
{
- Id = i.Id.ToString("N"),
- IsoType = i.IsoType,
+ Id = media.Id.ToString("N"),
+ IsoType = media.IsoType,
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
MediaStreams = mediaStreams,
- Name = GetMediaSourceName(i, mediaStreams),
- Path = enablePathSubstitution ? GetMappedPath(i, i.Path, locationType) : i.Path,
- RunTimeTicks = i.RunTimeTicks,
- Video3DFormat = i.Video3DFormat,
- VideoType = i.VideoType,
- Container = i.Container,
- Size = i.Size,
- Timestamp = i.Timestamp,
+ Name = GetMediaSourceName(media, mediaStreams),
+ Path = enablePathSubstitution ? GetMappedPath(media, media.Path, locationType) : media.Path,
+ RunTimeTicks = media.RunTimeTicks,
+ Video3DFormat = media.Video3DFormat,
+ VideoType = media.VideoType,
+ Container = media.Container,
+ Size = media.Size,
+ Timestamp = media.Timestamp,
Type = type,
- PlayableStreamFileNames = i.PlayableStreamFileNames.ToList(),
- SupportsDirectStream = i.VideoType == VideoType.VideoFile,
- IsRemote = i.IsShortcut
+ PlayableStreamFileNames = media.PlayableStreamFileNames.ToList(),
+ SupportsDirectStream = media.VideoType == VideoType.VideoFile,
+ IsRemote = media.IsShortcut
};
if (info.Protocol == MediaProtocol.File)
{
- info.ETag = i.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N");
+ info.ETag = media.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N");
}
- if (i.IsShortcut)
+ if (media.IsShortcut)
{
- info.Path = i.ShortcutPath;
+ info.Path = media.ShortcutPath;
if (info.Path.StartsWith("Http", StringComparison.OrdinalIgnoreCase))
{
@@ -647,16 +650,16 @@ namespace MediaBrowser.Controller.Entities
if (string.IsNullOrEmpty(info.Container))
{
- if (i.VideoType == VideoType.VideoFile || i.VideoType == VideoType.Iso)
+ if (media.VideoType == VideoType.VideoFile || media.VideoType == VideoType.Iso)
{
- if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
+ if (!string.IsNullOrWhiteSpace(media.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
{
- info.Container = System.IO.Path.GetExtension(i.Path).TrimStart('.');
+ info.Container = System.IO.Path.GetExtension(media.Path).TrimStart('.');
}
}
}
- info.Bitrate = i.TotalBitrate;
+ info.Bitrate = media.TotalBitrate;
info.InferTotalBitrate();
return info;
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index ebebe71a3..dd2379940 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -456,6 +456,8 @@ namespace MediaBrowser.Controller.Library
/// <returns>IEnumerable&lt;Folder&gt;.</returns>
List<Folder> GetCollectionFolders(BaseItem item);
+ List<Folder> GetCollectionFolders(BaseItem item, List<Folder> allUserRootChildren);
+
LibraryOptions GetLibraryOptions(BaseItem item);
/// <summary>
diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
index 763d27eba..3aa4d4ee2 100644
--- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs
+++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
@@ -114,7 +114,7 @@ namespace MediaBrowser.Controller.Library
return false;
}
- var parentDir = System.IO.Path.GetDirectoryName(Path) ?? string.Empty;
+ var parentDir = BaseItem.FileSystem.GetDirectoryName(Path) ?? string.Empty;
return parentDir.Length > _appPaths.RootFolderPath.Length
&& parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase);
@@ -130,7 +130,7 @@ namespace MediaBrowser.Controller.Library
{
get
{
- return IsDirectory && string.Equals(Path, _appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase);
+ return IsDirectory && BaseItem.FileSystem.AreEqual(Path, _appPaths.RootFolderPath);
}
}
@@ -300,7 +300,7 @@ namespace MediaBrowser.Controller.Library
if (args != null)
{
if (args.Path == null && Path == null) return true;
- return args.Path != null && args.Path.Equals(Path, StringComparison.OrdinalIgnoreCase);
+ return args.Path != null && BaseItem.FileSystem.AreEqual(args.Path, Path);
}
return false;
}
diff --git a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
index bcf39558e..0644719b6 100644
--- a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
+++ b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
@@ -16,6 +16,7 @@ namespace MediaBrowser.Controller.Library
public BaseItemInfo MediaInfo { get; set; }
public string MediaSourceId { get; set; }
public bool IsPaused { get; set; }
+ public bool IsAutomated { get; set; }
public string DeviceId { get; set; }
public string DeviceName { get; set; }
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
index fede81faf..6e2fe2495 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
@@ -16,7 +16,11 @@ namespace MediaBrowser.Controller.LiveTv
{
var list = base.GetUserDataKeys();
- list.Insert(0, GetClientTypeName() + "-" + Name);
+ if (!ConfigurationManager.Configuration.DisableLiveTvChannelUserDataName)
+ {
+ list.Insert(0, GetClientTypeName() + "-" + Name);
+ }
+
return list;
}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 22d09f34a..ca0b97a9f 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -732,7 +732,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (string.Equals(videoEncoder, "libx264", StringComparison.OrdinalIgnoreCase))
{
- param += " -x264opts:0 subme=0:rc_lookahead=10:me_range=4:me=dia:no_chroma_me:8x8dct=0:partitions=none";
+ param += " -x264opts:0 subme=0:me_range=4:rc_lookahead=10:me=dia:no_chroma_me:8x8dct=0:partitions=none";
}
if (!string.Equals(videoEncoder, "h264_omx", StringComparison.OrdinalIgnoreCase) &&
@@ -1517,12 +1517,6 @@ namespace MediaBrowser.Controller.MediaEncoding
inputModifier += " " + GetFastSeekCommandLineParameter(state.BaseRequest);
inputModifier = inputModifier.Trim();
- //inputModifier += " -fflags +genpts+ignidx+igndts";
- //if (state.IsVideoRequest && genPts)
- //{
- // inputModifier += " -fflags +genpts";
- //}
-
if (!string.IsNullOrEmpty(state.InputAudioSync))
{
inputModifier += " -async " + state.InputAudioSync;
@@ -1538,6 +1532,21 @@ namespace MediaBrowser.Controller.MediaEncoding
inputModifier += " -re";
}
+ var flags = new List<string>();
+ if (state.IgnoreDts)
+ {
+ flags.Add("+igndts");
+ }
+ if (state.IgnoreIndex)
+ {
+ flags.Add("+ignidx");
+ }
+
+ if (flags.Count > 0)
+ {
+ inputModifier += " -fflags " + string.Join("", flags.ToArray());
+ }
+
var videoDecoder = GetVideoDecoder(state, encodingOptions);
if (!string.IsNullOrWhiteSpace(videoDecoder))
{
@@ -1725,6 +1734,11 @@ namespace MediaBrowser.Controller.MediaEncoding
if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec))
{
+ if (!string.IsNullOrWhiteSpace(encodingOptions.HardwareAccelerationType))
+ {
+ return "-hwaccel auto";
+ }
+
if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
{
switch (state.MediaSource.VideoStream.Codec.ToLower())
@@ -1974,5 +1988,65 @@ namespace MediaBrowser.Controller.MediaEncoding
return args;
}
+
+ public string GetProgressiveAudioFullCommandLine(EncodingJobInfo state, EncodingOptions encodingOptions, string outputPath)
+ {
+ var audioTranscodeParams = new List<string>();
+
+ var bitrate = state.OutputAudioBitrate;
+
+ if (bitrate.HasValue)
+ {
+ audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(_usCulture));
+ }
+
+ if (state.OutputAudioChannels.HasValue)
+ {
+ audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(_usCulture));
+ }
+
+ // opus will fail on 44100
+ if (!string.Equals(state.OutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase))
+ {
+ if (state.OutputAudioSampleRate.HasValue)
+ {
+ audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(_usCulture));
+ }
+ }
+
+ var albumCoverInput = string.Empty;
+ var mapArgs = string.Empty;
+ var metadata = string.Empty;
+ var vn = string.Empty;
+
+ var hasArt = !string.IsNullOrWhiteSpace(state.AlbumCoverPath);
+
+ if (hasArt)
+ {
+ albumCoverInput = " -i \"" + state.AlbumCoverPath + "\"";
+ mapArgs = " -map 0:a -map 1:v -c:1:v copy";
+ metadata = " -metadata:s:v title=\"Album cover\" -metadata:s:v comment=\"Cover(Front)\"";
+ }
+ else
+ {
+ vn = " -vn";
+ }
+
+ var threads = GetNumberOfThreads(state, encodingOptions, false);
+
+ var inputModifier = GetInputModifier(state, encodingOptions);
+
+ return string.Format("{0} {1}{7}{8} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1{6} -y \"{5}\"",
+ inputModifier,
+ GetInputArgument(state, encodingOptions),
+ threads,
+ vn,
+ string.Join(" ", audioTranscodeParams.ToArray()),
+ outputPath,
+ metadata,
+ albumCoverInput,
+ mapArgs).Trim();
+ }
+
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
index f3e6280aa..28ada9dae 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
@@ -39,6 +39,16 @@ namespace MediaBrowser.Controller.MediaEncoding
public bool ReadInputAtNativeFramerate { get; set; }
+ public bool IgnoreDts
+ {
+ get { return MediaSource.IgnoreDts; }
+ }
+
+ public bool IgnoreIndex
+ {
+ get { return MediaSource.IgnoreIndex; }
+ }
+
public string OutputContainer { get; set; }
public string OutputVideoSync
@@ -56,6 +66,8 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
+ public string AlbumCoverPath { get; set; }
+
public string InputAudioSync { get; set; }
public string InputVideoSync { get; set; }
public TransportStreamTimestamp InputTimestamp { get; set; }
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index 78ed1dc59..bac9807a9 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -126,7 +126,6 @@ namespace MediaBrowser.Controller.MediaEncoding
Task UpdateEncoderPath(string path, string pathType);
bool SupportsEncoder(string encoder);
- bool IsDefaultEncoderPath { get; }
void SetLogFilename(string name);
void ClearLogFilename();
diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs
index 0eb435375..fb1410f4a 100644
--- a/MediaBrowser.Controller/Playlists/Playlist.cs
+++ b/MediaBrowser.Controller/Playlists/Playlist.cs
@@ -134,34 +134,27 @@ namespace MediaBrowser.Controller.Playlists
var musicGenre = item as MusicGenre;
if (musicGenre != null)
{
- var items = LibraryManager.GetItemList(new InternalItemsQuery(user)
+ return LibraryManager.GetItemList(new InternalItemsQuery(user)
{
Recursive = true,
IncludeItemTypes = new[] { typeof(Audio).Name },
- Genres = new[] { musicGenre.Name }
+ GenreIds = new[] { musicGenre.Id.ToString("N") },
+ SortBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName },
+ SortOrder = SortOrder.Ascending
});
-
- return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
}
var musicArtist = item as MusicArtist;
if (musicArtist != null)
{
- Func<BaseItem, bool> filter = i =>
+ return LibraryManager.GetItemList(new InternalItemsQuery(user)
{
- var audio = i as Audio;
- return audio != null && audio.HasAnyArtist(musicArtist.Name);
- };
-
- var items = user == null
- ? LibraryManager.RootFolder.GetRecursiveChildren(filter)
- : user.RootFolder.GetRecursiveChildren(user, new InternalItemsQuery(user)
- {
- IncludeItemTypes = new[] { typeof(Audio).Name },
- ArtistIds = new[] { musicArtist.Id.ToString("N") }
- });
-
- return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
+ Recursive = true,
+ IncludeItemTypes = new[] { typeof(Audio).Name },
+ ArtistIds = new[] { musicArtist.Id.ToString("N") },
+ SortBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName },
+ SortOrder = SortOrder.Ascending
+ });
}
var folder = item as Folder;
diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs
index 40093df3a..62db007b9 100644
--- a/MediaBrowser.Controller/Providers/DirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/DirectoryService.cs
@@ -63,11 +63,11 @@ namespace MediaBrowser.Controller.Providers
//_logger.Debug("Getting files for " + path);
entries = new Dictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase);
-
+
try
{
// using EnumerateFileSystemInfos doesn't handle reparse points (symlinks)
- var list = _fileSystem.GetFileSystemEntries(path)
+ var list = _fileSystem.GetFileSystemEntries(path)
.ToList();
// Seeing dupes on some users file system for some reason
@@ -80,7 +80,7 @@ namespace MediaBrowser.Controller.Providers
{
}
- //var group = entries.ToLookup(i => Path.GetDirectoryName(i.FullName)).ToList();
+ //var group = entries.ToLookup(i => _fileSystem.GetDirectoryName(i.FullName)).ToList();
_cache.TryAdd(path, entries);
}
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index f4d45c7e0..c0bc90214 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -20,9 +20,7 @@ namespace MediaBrowser.Controller.Providers
/// <summary>
/// Queues the refresh.
/// </summary>
- /// <param name="itemId">The item identifier.</param>
- /// <param name="options">The options.</param>
- void QueueRefresh(Guid itemId, MetadataRefreshOptions options);
+ void QueueRefresh(Guid itemId, MetadataRefreshOptions options, RefreshPriority priority);
/// <summary>
/// Refreshes the full item.
@@ -161,4 +159,11 @@ namespace MediaBrowser.Controller.Providers
/// <returns>Task{HttpResponseInfo}.</returns>
Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);
}
+
+ public enum RefreshPriority
+ {
+ High = 0,
+ Normal = 1,
+ Low = 2
+ }
} \ No newline at end of file
diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
index e005ad224..bd33dece8 100644
--- a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
@@ -38,7 +38,7 @@ namespace MediaBrowser.LocalMetadata.Images
public List<LocalImageInfo> GetImages(IHasImages item, IDirectoryService directoryService)
{
- var parentPath = Path.GetDirectoryName(item.Path);
+ var parentPath = _fileSystem.GetDirectoryName(item.Path);
var parentPathFiles = directoryService.GetFileSystemEntries(parentPath)
.ToList();
diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs
index e56bfb49c..2500ee482 100644
--- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs
@@ -246,18 +246,6 @@ namespace MediaBrowser.LocalMetadata.Parsers
break;
}
- case "CriticRatingSummary":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.CriticRatingSummary = val;
- }
-
- break;
- }
-
case "Language":
{
var val = reader.ReadElementContentAsString();
@@ -377,17 +365,6 @@ namespace MediaBrowser.LocalMetadata.Parsers
break;
}
- case "MPAADescription":
- {
- var rating = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(rating))
- {
- item.OfficialRatingDescription = rating;
- }
- break;
- }
-
case "CustomRating":
{
var val = reader.ReadElementContentAsString();
diff --git a/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs
index 9adc4e5a9..69d799b18 100644
--- a/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs
@@ -84,7 +84,7 @@ namespace MediaBrowser.LocalMetadata.Parsers
// even though it's actually using the metadata folder.
filename = Path.GetFileName(filename);
- var parentFolder = Path.GetDirectoryName(_xmlPath);
+ var parentFolder = _fileSystem.GetDirectoryName(_xmlPath);
filename = Path.Combine(parentFolder, filename);
var file = _fileSystem.GetFileInfo(filename);
diff --git a/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs
index 7e0f1707f..fda8ea6d0 100644
--- a/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs
@@ -39,7 +39,7 @@ namespace MediaBrowser.LocalMetadata.Providers
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
{
- var metadataPath = Path.GetDirectoryName(info.Path);
+ var metadataPath = FileSystem.GetDirectoryName(info.Path);
metadataPath = Path.Combine(metadataPath, "metadata");
var metadataFile = Path.Combine(metadataPath, Path.ChangeExtension(Path.GetFileName(info.Path), ".xml"));
diff --git a/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs
index 888eff416..8ed18df64 100644
--- a/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs
@@ -35,7 +35,7 @@ namespace MediaBrowser.LocalMetadata.Providers
var specificFile = Path.ChangeExtension(info.Path, ".xml");
var file = FileSystem.GetFileInfo(specificFile);
- return info.IsInMixedFolder || file.Exists ? file : FileSystem.GetFileInfo(Path.Combine(Path.GetDirectoryName(info.Path), "game.xml"));
+ return info.IsInMixedFolder || file.Exists ? file : FileSystem.GetFileInfo(Path.Combine(FileSystem.GetDirectoryName(info.Path), "game.xml"));
}
}
}
diff --git a/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs
index 0e59db75f..2d4059a1a 100644
--- a/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs
@@ -39,7 +39,7 @@ namespace MediaBrowser.LocalMetadata.Providers
{
var fileInfo = fileSystem.GetFileSystemInfo(info.Path);
- var directoryInfo = fileInfo.IsDirectory ? fileInfo : fileSystem.GetDirectoryInfo(Path.GetDirectoryName(info.Path));
+ var directoryInfo = fileInfo.IsDirectory ? fileInfo : fileSystem.GetDirectoryInfo(fileSystem.GetDirectoryName(info.Path));
var directoryPath = directoryInfo.FullName;
diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
index 105e685f4..a3a55176c 100644
--- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
@@ -46,7 +46,6 @@ namespace MediaBrowser.LocalMetadata.Savers
"Countries",
"CustomRating",
"CriticRating",
- "CriticRatingSummary",
"DeathDate",
"DisplayOrder",
"EndDate",
@@ -72,8 +71,6 @@ namespace MediaBrowser.LocalMetadata.Savers
// Deprecated. No longer saving in this field.
"MPAARating",
- "MPAADescription",
-
"MusicBrainzArtistId",
"MusicBrainzAlbumArtistId",
"MusicBrainzAlbumId",
@@ -210,7 +207,7 @@ namespace MediaBrowser.LocalMetadata.Savers
private void SaveToFile(Stream stream, string path)
{
- FileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path));
var file = FileSystem.GetFileInfo(path);
@@ -309,11 +306,6 @@ namespace MediaBrowser.LocalMetadata.Savers
writer.WriteElementString("ContentRating", item.OfficialRating);
}
- if (!string.IsNullOrEmpty(item.OfficialRatingDescription))
- {
- writer.WriteElementString("MPAADescription", item.OfficialRatingDescription);
- }
-
writer.WriteElementString("Added", item.DateCreated.ToLocalTime().ToString("G"));
writer.WriteElementString("LockData", item.IsLocked.ToString().ToLower());
@@ -333,11 +325,6 @@ namespace MediaBrowser.LocalMetadata.Savers
writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(UsCulture));
}
- if (!string.IsNullOrEmpty(item.CriticRatingSummary))
- {
- writer.WriteElementString("CriticRatingSummary", item.CriticRatingSummary);
- }
-
if (!string.IsNullOrEmpty(item.Overview))
{
writer.WriteElementString("Overview", item.Overview);
diff --git a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs
index 05b3ca5fc..566e7946d 100644
--- a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs
@@ -5,8 +5,6 @@ using MediaBrowser.Controller.Session;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
using MediaBrowser.Model.Diagnostics;
namespace MediaBrowser.MediaEncoding.Encoder
@@ -19,66 +17,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
protected override string GetCommandLineArguments(EncodingJob state)
{
- var audioTranscodeParams = new List<string>();
-
- var bitrate = state.OutputAudioBitrate;
-
- if (bitrate.HasValue)
- {
- audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(UsCulture));
- }
-
- if (state.OutputAudioChannels.HasValue)
- {
- audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(UsCulture));
- }
-
- // opus will fail on 44100
- if (!string.Equals(state.OutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase))
- {
- if (state.OutputAudioSampleRate.HasValue)
- {
- audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(UsCulture));
- }
- }
-
var encodingOptions = GetEncodingOptions();
- var threads = EncodingHelper.GetNumberOfThreads(state, encodingOptions, false);
-
- var inputModifier = EncodingHelper.GetInputModifier(state, encodingOptions);
-
- var albumCoverInput = string.Empty;
- var mapArgs = string.Empty;
- var metadata = string.Empty;
- var vn = string.Empty;
-
- var hasArt = !string.IsNullOrWhiteSpace(state.AlbumCoverPath);
- hasArt = false;
-
- if (hasArt)
- {
- albumCoverInput = " -i \"" + state.AlbumCoverPath + "\"";
- mapArgs = " -map 0:a -map 1:v -c:v copy";
- metadata = " -metadata:s:v title=\"Album cover\" -metadata:s:v comment=\"Cover(Front)\"";
- }
- else
- {
- vn = " -vn";
- }
-
- var result = string.Format("{0} {1}{6}{7} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1{8} -y \"{5}\"",
- inputModifier,
- EncodingHelper.GetInputArgument(state, GetEncodingOptions()),
- threads,
- vn,
- string.Join(" ", audioTranscodeParams.ToArray()),
- state.OutputFilePath,
- albumCoverInput,
- mapArgs,
- metadata).Trim();
-
- return result;
+ return EncodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, state.OutputFilePath);
}
protected override string GetOutputFileExtension(EncodingJob state)
diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
index e402c2bac..3672e4e84 100644
--- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
@@ -70,7 +70,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
.CreateJob(options, EncodingHelper, IsVideoEncoder, progress, cancellationToken).ConfigureAwait(false);
encodingJob.OutputFilePath = GetOutputFilePath(encodingJob);
- FileSystem.CreateDirectory(Path.GetDirectoryName(encodingJob.OutputFilePath));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(encodingJob.OutputFilePath));
encodingJob.ReadInputAtNativeFramerate = options.ReadInputAtNativeFramerate;
@@ -108,7 +108,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
Logger.Info(commandLineLogMessage);
var logFilePath = Path.Combine(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath, "transcode-" + Guid.NewGuid() + ".txt");
- FileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(logFilePath));
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
encodingJob.LogFileStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true);
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs
index f74dbce98..9d518c431 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs
@@ -41,8 +41,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
public string ItemType { get; set; }
- public string AlbumCoverPath { get; set; }
-
public string GetMimeType(string outputPath)
{
if (!string.IsNullOrEmpty(MimeType))
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
index 498df214f..dc3cb5f5e 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs
@@ -45,6 +45,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// <returns>System.String.</returns>
private static string GetFileInputArgument(string path)
{
+ if (path.IndexOf("://") != -1)
+ {
+ return string.Format("\"{0}\"", path);
+ }
+
// Quotes are valid path characters in linux and they need to be escaped here with a leading \
path = NormalizePath(path);
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 816f14f82..c58a18b0f 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -49,11 +49,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// </summary>
private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(1, 1);
- /// <summary>
- /// The FF probe resource pool
- /// </summary>
- private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(2, 2);
-
public string FFMpegPath { get; private set; }
public string FFProbePath { get; private set; }
@@ -192,18 +187,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
}
- public bool IsDefaultEncoderPath
- {
- get
- {
- var path = FFMpegPath;
-
- var parentPath = Path.Combine(ConfigurationManager.ApplicationPaths.ProgramDataPath, "ffmpeg", "20160410");
-
- return FileSystem.ContainsSubPath(parentPath, path);
- }
- }
-
private bool IsSystemInstalledPath(string path)
{
if (path.IndexOf("/", StringComparison.Ordinal) == -1 && path.IndexOf("\\", StringComparison.Ordinal) == -1)
@@ -227,12 +210,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (EnableEncoderFontFile)
{
- var directory = Path.GetDirectoryName(FFMpegPath);
+ var directory = FileSystem.GetDirectoryName(FFMpegPath);
if (!string.IsNullOrWhiteSpace(directory) && FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.ProgramDataPath, directory))
{
- await new FontConfigLoader(_httpClient, ConfigurationManager.ApplicationPaths, _logger, _zipClient,
- FileSystem).DownloadFonts(directory).ConfigureAwait(false);
+ await new FontConfigLoader(_httpClient, ConfigurationManager.ApplicationPaths, _logger, _zipClient, FileSystem).DownloadFonts(directory).ConfigureAwait(false);
}
}
}
@@ -433,7 +415,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
private string GetProbePathFromEncoderPath(string appPath)
{
- return FileSystem.GetFilePaths(Path.GetDirectoryName(appPath))
+ return FileSystem.GetFilePaths(FileSystem.GetDirectoryName(appPath))
.FirstOrDefault(i => string.Equals(Path.GetFileNameWithoutExtension(i), "ffprobe", StringComparison.OrdinalIgnoreCase));
}
@@ -591,20 +573,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
using (var processWrapper = new ProcessWrapper(process, this, _logger))
{
- await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- try
- {
- StartProcess(processWrapper);
- }
- catch (Exception ex)
- {
- _ffProbeResourcePool.Release();
-
- _logger.ErrorException("Error starting ffprobe", ex);
-
- throw;
- }
+ StartProcess(processWrapper);
try
{
@@ -655,10 +624,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
throw;
}
- finally
- {
- _ffProbeResourcePool.Release();
- }
}
}
@@ -739,7 +704,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
var tempExtractPath = Path.Combine(ConfigurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg");
- FileSystem.CreateDirectory(Path.GetDirectoryName(tempExtractPath));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(tempExtractPath));
// apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar then scale to width 600.
// This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 231a2ae85..1e983ca15 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -412,7 +412,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
throw new ArgumentNullException("outputPath");
}
- _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath));
var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, inputProtocol, cancellationToken).ConfigureAwait(false);
@@ -524,8 +524,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
if (!_fileSystem.FileExists(outputPath))
{
- await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), subtitleStreamIndex,
- outputCodec, outputPath, cancellationToken).ConfigureAwait(false);
+ await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), subtitleStreamIndex, outputCodec, outputPath, cancellationToken).ConfigureAwait(false);
}
}
finally
@@ -547,7 +546,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
throw new ArgumentNullException("outputPath");
}
- _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath));
var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath,
subtitleStreamIndex, outputCodec, outputPath);
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 9d795cfab..838111a38 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -68,6 +68,8 @@ namespace MediaBrowser.Model.Configuration
/// <value><c>true</c> if [enable case sensitive item ids]; otherwise, <c>false</c>.</value>
public bool EnableCaseSensitiveItemIds { get; set; }
+ public bool DisableLiveTvChannelUserDataName { get; set; }
+
/// <summary>
/// Gets or sets the metadata path.
/// </summary>
@@ -162,7 +164,6 @@ namespace MediaBrowser.Model.Configuration
public bool EnableAutomaticRestart { get; set; }
public bool SkipDeserializationForBasicTypes { get; set; }
- public bool SkipDeserializationForPrograms { get; set; }
public bool SkipDeserializationForAudio { get; set; }
public string ServerName { get; set; }
diff --git a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs
index b0760d91f..950d3680d 100644
--- a/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs
+++ b/MediaBrowser.Model/Dlna/ResolutionNormalizer.cs
@@ -12,7 +12,9 @@ namespace MediaBrowser.Model.Dlna
new ResolutionConfiguration(426, 320000),
new ResolutionConfiguration(640, 400000),
new ResolutionConfiguration(720, 950000),
- new ResolutionConfiguration(1280, 2500000)
+ new ResolutionConfiguration(1280, 2500000),
+ new ResolutionConfiguration(1920, 4000000),
+ new ResolutionConfiguration(3840, 35000000)
};
public static ResolutionOptions Normalize(int? inputBitrate,
@@ -35,19 +37,15 @@ namespace MediaBrowser.Model.Dlna
}
}
- foreach (var config in Configurations)
+ var resolutionConfig = GetResolutionConfiguration(outputBitrate);
+ if (resolutionConfig != null)
{
- if (outputBitrate <= config.MaxBitrate)
- {
- var originvalValue = maxWidth;
-
- maxWidth = Math.Min(config.MaxWidth, maxWidth ?? config.MaxWidth);
- if (!originvalValue.HasValue || originvalValue.Value != maxWidth.Value)
- {
- maxHeight = null;
- }
+ var originvalValue = maxWidth;
- break;
+ maxWidth = Math.Min(resolutionConfig.MaxWidth, maxWidth ?? resolutionConfig.MaxWidth);
+ if (!originvalValue.HasValue || originvalValue.Value != maxWidth.Value)
+ {
+ maxHeight = null;
}
}
@@ -58,6 +56,19 @@ namespace MediaBrowser.Model.Dlna
};
}
+ private static ResolutionConfiguration GetResolutionConfiguration(int outputBitrate)
+ {
+ foreach (var config in Configurations)
+ {
+ if (outputBitrate <= config.MaxBitrate)
+ {
+ return config;
+ }
+ }
+
+ return null;
+ }
+
private static double GetVideoBitrateScaleFactor(string codec)
{
if (StringHelper.EqualsIgnoreCase(codec, "h265") ||
diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs
index ae7d13868..1a752892e 100644
--- a/MediaBrowser.Model/Dto/BaseItemDto.cs
+++ b/MediaBrowser.Model/Dto/BaseItemDto.cs
@@ -165,12 +165,6 @@ namespace MediaBrowser.Model.Dto
public string[] ProductionLocations { get; set; }
- /// <summary>
- /// Gets or sets the critic rating summary.
- /// </summary>
- /// <value>The critic rating summary.</value>
- public string CriticRatingSummary { get; set; }
-
public List<string> MultiPartGameFiles { get; set; }
/// <summary>
diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs
index 131583024..d0655d90b 100644
--- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs
+++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs
@@ -29,6 +29,8 @@ namespace MediaBrowser.Model.Dto
public string ETag { get; set; }
public long? RunTimeTicks { get; set; }
public bool ReadAtNativeFramerate { get; set; }
+ public bool IgnoreDts { get; set; }
+ public bool IgnoreIndex { get; set; }
public bool SupportsTranscoding { get; set; }
public bool SupportsDirectStream { get; set; }
public bool SupportsDirectPlay { get; set; }
diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs
index 6773acbfa..26de9332e 100644
--- a/MediaBrowser.Model/IO/IFileSystem.cs
+++ b/MediaBrowser.Model/IO/IFileSystem.cs
@@ -146,6 +146,8 @@ namespace MediaBrowser.Model.IO
/// <returns>System.String.</returns>
string NormalizePath(string path);
+ string GetDirectoryName(string path);
+
/// <summary>
/// Gets the file name without extension.
/// </summary>
diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs
index 0caf64538..75ba09b60 100644
--- a/MediaBrowser.Model/Querying/ItemFields.cs
+++ b/MediaBrowser.Model/Querying/ItemFields.cs
@@ -43,11 +43,6 @@
ChildCount,
/// <summary>
- /// The critic rating summary
- /// </summary>
- CriticRatingSummary,
-
- /// <summary>
/// The cumulative run time ticks
/// </summary>
CumulativeRunTimeTicks,
@@ -122,8 +117,6 @@
/// </summary>
MediaSources,
- OfficialRatingDescription,
-
OriginalTitle,
/// <summary>
diff --git a/MediaBrowser.Model/Search/SearchHint.cs b/MediaBrowser.Model/Search/SearchHint.cs
index cea15a2a7..3ca0eafe6 100644
--- a/MediaBrowser.Model/Search/SearchHint.cs
+++ b/MediaBrowser.Model/Search/SearchHint.cs
@@ -1,4 +1,6 @@
-namespace MediaBrowser.Model.Search
+using System;
+
+namespace MediaBrowser.Model.Search
{
/// <summary>
/// Class SearchHintResult
@@ -94,13 +96,18 @@
/// </summary>
/// <value>The display type of the media.</value>
public string DisplayMediaType { get; set; }
-
+
+ public DateTime? StartDate { get; set; }
+ public DateTime? EndDate { get; set; }
+
/// <summary>
/// Gets or sets the series.
/// </summary>
/// <value>The series.</value>
public string Series { get; set; }
+ public string Status { get; set; }
+
/// <summary>
/// Gets or sets the album.
/// </summary>
diff --git a/MediaBrowser.Model/Search/SearchQuery.cs b/MediaBrowser.Model/Search/SearchQuery.cs
index 678dfd39d..897a9db52 100644
--- a/MediaBrowser.Model/Search/SearchQuery.cs
+++ b/MediaBrowser.Model/Search/SearchQuery.cs
@@ -34,6 +34,17 @@ namespace MediaBrowser.Model.Search
public bool IncludeArtists { get; set; }
public string[] IncludeItemTypes { get; set; }
+ public string ParentId { get; set; }
+
+ public bool? IsMovie { get; set; }
+
+ public bool? IsSeries { get; set; }
+
+ public bool? IsNews { get; set; }
+
+ public bool? IsKids { get; set; }
+
+ public bool? IsSports { get; set; }
public SearchQuery()
{
diff --git a/MediaBrowser.Model/Session/GeneralCommandType.cs b/MediaBrowser.Model/Session/GeneralCommandType.cs
index 6cceb162a..1a9651559 100644
--- a/MediaBrowser.Model/Session/GeneralCommandType.cs
+++ b/MediaBrowser.Model/Session/GeneralCommandType.cs
@@ -37,6 +37,7 @@
SetRepeatMode = 29,
ChannelUp = 30,
ChannelDown = 31,
- SetMaxStreamingBitrate = 31
+ SetMaxStreamingBitrate = 31,
+ Guide = 32
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs
index 3917b1662..2a987ceb1 100644
--- a/MediaBrowser.Model/Users/UserPolicy.cs
+++ b/MediaBrowser.Model/Users/UserPolicy.cs
@@ -50,7 +50,6 @@ namespace MediaBrowser.Model.Users
/// Gets or sets a value indicating whether [enable synchronize].
/// </summary>
/// <value><c>true</c> if [enable synchronize]; otherwise, <c>false</c>.</value>
- public bool EnableSync { get; set; }
public bool EnableSyncTranscoding { get; set; }
public string[] EnabledDevices { get; set; }
@@ -71,7 +70,6 @@ namespace MediaBrowser.Model.Users
public UserPolicy()
{
- EnableSync = true;
EnableSyncTranscoding = true;
EnableMediaPlayback = true;
diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
index 547420092..6175c3622 100644
--- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
+++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
@@ -158,7 +158,7 @@ namespace MediaBrowser.Providers.BoxSets
var dataFilePath = GetDataFilePath(_config.ApplicationPaths, tmdbId, preferredMetadataLanguage);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
_json.SerializeToFile(mainResult, dataFilePath);
}
diff --git a/MediaBrowser.Providers/ImagesByName/ImageUtils.cs b/MediaBrowser.Providers/ImagesByName/ImageUtils.cs
index bbcbbda90..566378dd0 100644
--- a/MediaBrowser.Providers/ImagesByName/ImageUtils.cs
+++ b/MediaBrowser.Providers/ImagesByName/ImageUtils.cs
@@ -6,8 +6,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.IO;
using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.ImagesByName
@@ -21,36 +19,37 @@ namespace MediaBrowser.Providers.ImagesByName
/// <param name="file">The file.</param>
/// <param name="httpClient">The HTTP client.</param>
/// <param name="fileSystem">The file system.</param>
- /// <param name="semaphore">The semaphore.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- public static async Task EnsureList(string url, string file, IHttpClient httpClient, IFileSystem fileSystem, SemaphoreSlim semaphore, CancellationToken cancellationToken)
+ public static async Task<string> EnsureList(string url, string file, IHttpClient httpClient, IFileSystem fileSystem, CancellationToken cancellationToken)
{
var fileInfo = fileSystem.GetFileInfo(file);
if (!fileInfo.Exists || (DateTime.UtcNow - fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays > 1)
{
- await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- try
+ var temp = await httpClient.GetTempFile(new HttpRequestOptions
{
- var temp = await httpClient.GetTempFile(new HttpRequestOptions
- {
- CancellationToken = cancellationToken,
- Progress = new Progress<double>(),
- Url = url
+ CancellationToken = cancellationToken,
+ Progress = new Progress<double>(),
+ Url = url
- }).ConfigureAwait(false);
+ }).ConfigureAwait(false);
- fileSystem.CreateDirectory(Path.GetDirectoryName(file));
+ fileSystem.CreateDirectory(fileSystem.GetDirectoryName(file));
- fileSystem.CopyFile(temp, file, true);
+ try
+ {
+ fileSystem.CopyFile(temp, file, true);
}
- finally
+ catch
{
- semaphore.Release();
+
}
+
+ return temp;
}
+
+ return file;
}
public static string FindMatch(IHasImages item, IEnumerable<string> images)
diff --git a/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs b/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs
new file mode 100644
index 000000000..03bb0f68c
--- /dev/null
+++ b/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs
@@ -0,0 +1,429 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Priority_Queue
+{
+ /// <summary>
+ /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
+ /// A copy of StablePriorityQueue which also has generic priority-type
+ /// </summary>
+ /// <typeparam name="TItem">The values in the queue. Must extend the GenericPriorityQueue class</typeparam>
+ /// <typeparam name="TPriority">The priority-type. Must extend IComparable&lt;TPriority&gt;</typeparam>
+ public sealed class GenericPriorityQueue<TItem, TPriority> : IFixedSizePriorityQueue<TItem, TPriority>
+ where TItem : GenericPriorityQueueNode<TPriority>
+ where TPriority : IComparable<TPriority>
+ {
+ private int _numNodes;
+ private TItem[] _nodes;
+ private long _numNodesEverEnqueued;
+
+ /// <summary>
+ /// Instantiate a new Priority Queue
+ /// </summary>
+ /// <param name="maxNodes">The max nodes ever allowed to be enqueued (going over this will cause undefined behavior)</param>
+ public GenericPriorityQueue(int maxNodes)
+ {
+#if DEBUG
+ if (maxNodes <= 0)
+ {
+ throw new InvalidOperationException("New queue size cannot be smaller than 1");
+ }
+#endif
+
+ _numNodes = 0;
+ _nodes = new TItem[maxNodes + 1];
+ _numNodesEverEnqueued = 0;
+ }
+
+ /// <summary>
+ /// Returns the number of nodes in the queue.
+ /// O(1)
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ return _numNodes;
+ }
+ }
+
+ /// <summary>
+ /// Returns the maximum number of items that can be enqueued at once in this queue. Once you hit this number (ie. once Count == MaxSize),
+ /// attempting to enqueue another item will cause undefined behavior. O(1)
+ /// </summary>
+ public int MaxSize
+ {
+ get
+ {
+ return _nodes.Length - 1;
+ }
+ }
+
+ /// <summary>
+ /// Removes every node from the queue.
+ /// O(n) (So, don't do this often!)
+ /// </summary>
+#if NET_VERSION_4_5
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ public void Clear()
+ {
+ Array.Clear(_nodes, 1, _numNodes);
+ _numNodes = 0;
+ }
+
+ /// <summary>
+ /// Returns (in O(1)!) whether the given node is in the queue. O(1)
+ /// </summary>
+#if NET_VERSION_4_5
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ public bool Contains(TItem node)
+ {
+#if DEBUG
+ if (node == null)
+ {
+ throw new ArgumentNullException("node");
+ }
+ if (node.QueueIndex < 0 || node.QueueIndex >= _nodes.Length)
+ {
+ throw new InvalidOperationException("node.QueueIndex has been corrupted. Did you change it manually? Or add this node to another queue?");
+ }
+#endif
+
+ return (_nodes[node.QueueIndex] == node);
+ }
+
+ /// <summary>
+ /// Enqueue a node to the priority queue. Lower values are placed in front. Ties are broken by first-in-first-out.
+ /// If the queue is full, the result is undefined.
+ /// If the node is already enqueued, the result is undefined.
+ /// O(log n)
+ /// </summary>
+#if NET_VERSION_4_5
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ public void Enqueue(TItem node, TPriority priority)
+ {
+#if DEBUG
+ if (node == null)
+ {
+ throw new ArgumentNullException("node");
+ }
+ if (_numNodes >= _nodes.Length - 1)
+ {
+ throw new InvalidOperationException("Queue is full - node cannot be added: " + node);
+ }
+ if (Contains(node))
+ {
+ throw new InvalidOperationException("Node is already enqueued: " + node);
+ }
+#endif
+
+ node.Priority = priority;
+ _numNodes++;
+ _nodes[_numNodes] = node;
+ node.QueueIndex = _numNodes;
+ node.InsertionIndex = _numNodesEverEnqueued++;
+ CascadeUp(_nodes[_numNodes]);
+ }
+
+#if NET_VERSION_4_5
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ private void Swap(TItem node1, TItem node2)
+ {
+ //Swap the nodes
+ _nodes[node1.QueueIndex] = node2;
+ _nodes[node2.QueueIndex] = node1;
+
+ //Swap their indicies
+ int temp = node1.QueueIndex;
+ node1.QueueIndex = node2.QueueIndex;
+ node2.QueueIndex = temp;
+ }
+
+ //Performance appears to be slightly better when this is NOT inlined o_O
+ private void CascadeUp(TItem node)
+ {
+ //aka Heapify-up
+ int parent = node.QueueIndex / 2;
+ while (parent >= 1)
+ {
+ TItem parentNode = _nodes[parent];
+ if (HasHigherPriority(parentNode, node))
+ break;
+
+ //Node has lower priority value, so move it up the heap
+ Swap(node, parentNode); //For some reason, this is faster with Swap() rather than (less..?) individual operations, like in CascadeDown()
+
+ parent = node.QueueIndex / 2;
+ }
+ }
+
+#if NET_VERSION_4_5
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ private void CascadeDown(TItem node)
+ {
+ //aka Heapify-down
+ TItem newParent;
+ int finalQueueIndex = node.QueueIndex;
+ while (true)
+ {
+ newParent = node;
+ int childLeftIndex = 2 * finalQueueIndex;
+
+ //Check if the left-child is higher-priority than the current node
+ if (childLeftIndex > _numNodes)
+ {
+ //This could be placed outside the loop, but then we'd have to check newParent != node twice
+ node.QueueIndex = finalQueueIndex;
+ _nodes[finalQueueIndex] = node;
+ break;
+ }
+
+ TItem childLeft = _nodes[childLeftIndex];
+ if (HasHigherPriority(childLeft, newParent))
+ {
+ newParent = childLeft;
+ }
+
+ //Check if the right-child is higher-priority than either the current node or the left child
+ int childRightIndex = childLeftIndex + 1;
+ if (childRightIndex <= _numNodes)
+ {
+ TItem childRight = _nodes[childRightIndex];
+ if (HasHigherPriority(childRight, newParent))
+ {
+ newParent = childRight;
+ }
+ }
+
+ //If either of the children has higher (smaller) priority, swap and continue cascading
+ if (newParent != node)
+ {
+ //Move new parent to its new index. node will be moved once, at the end
+ //Doing it this way is one less assignment operation than calling Swap()
+ _nodes[finalQueueIndex] = newParent;
+
+ int temp = newParent.QueueIndex;
+ newParent.QueueIndex = finalQueueIndex;
+ finalQueueIndex = temp;
+ }
+ else
+ {
+ //See note above
+ node.QueueIndex = finalQueueIndex;
+ _nodes[finalQueueIndex] = node;
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns true if 'higher' has higher priority than 'lower', false otherwise.
+ /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false
+ /// </summary>
+#if NET_VERSION_4_5
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ private bool HasHigherPriority(TItem higher, TItem lower)
+ {
+ var cmp = higher.Priority.CompareTo(lower.Priority);
+ return (cmp < 0 || (cmp == 0 && higher.InsertionIndex < lower.InsertionIndex));
+ }
+
+ /// <summary>
+ /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it.
+ /// If queue is empty, result is undefined
+ /// O(log n)
+ /// </summary>
+ public bool TryDequeue(out TItem item)
+ {
+ if (_numNodes <= 0)
+ {
+ item = default(TItem);
+ return false;
+ }
+
+#if DEBUG
+
+ if (!IsValidQueue())
+ {
+ throw new InvalidOperationException("Queue has been corrupted (Did you update a node priority manually instead of calling UpdatePriority()?" +
+ "Or add the same node to two different queues?)");
+ }
+#endif
+
+ TItem returnMe = _nodes[1];
+ Remove(returnMe);
+ item = returnMe;
+ return true;
+ }
+
+ /// <summary>
+ /// Resize the queue so it can accept more nodes. All currently enqueued nodes are remain.
+ /// Attempting to decrease the queue size to a size too small to hold the existing nodes results in undefined behavior
+ /// O(n)
+ /// </summary>
+ public void Resize(int maxNodes)
+ {
+#if DEBUG
+ if (maxNodes <= 0)
+ {
+ throw new InvalidOperationException("Queue size cannot be smaller than 1");
+ }
+
+ if (maxNodes < _numNodes)
+ {
+ throw new InvalidOperationException("Called Resize(" + maxNodes + "), but current queue contains " + _numNodes + " nodes");
+ }
+#endif
+
+ TItem[] newArray = new TItem[maxNodes + 1];
+ int highestIndexToCopy = Math.Min(maxNodes, _numNodes);
+ for (int i = 1; i <= highestIndexToCopy; i++)
+ {
+ newArray[i] = _nodes[i];
+ }
+ _nodes = newArray;
+ }
+
+ /// <summary>
+ /// Returns the head of the queue, without removing it (use Dequeue() for that).
+ /// If the queue is empty, behavior is undefined.
+ /// O(1)
+ /// </summary>
+ public TItem First
+ {
+ get
+ {
+#if DEBUG
+ if (_numNodes <= 0)
+ {
+ throw new InvalidOperationException("Cannot call .First on an empty queue");
+ }
+#endif
+
+ return _nodes[1];
+ }
+ }
+
+ /// <summary>
+ /// This method must be called on a node every time its priority changes while it is in the queue.
+ /// <b>Forgetting to call this method will result in a corrupted queue!</b>
+ /// Calling this method on a node not in the queue results in undefined behavior
+ /// O(log n)
+ /// </summary>
+#if NET_VERSION_4_5
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+ public void UpdatePriority(TItem node, TPriority priority)
+ {
+#if DEBUG
+ if (node == null)
+ {
+ throw new ArgumentNullException("node");
+ }
+ if (!Contains(node))
+ {
+ throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + node);
+ }
+#endif
+
+ node.Priority = priority;
+ OnNodeUpdated(node);
+ }
+
+ private void OnNodeUpdated(TItem node)
+ {
+ //Bubble the updated node up or down as appropriate
+ int parentIndex = node.QueueIndex / 2;
+ TItem parentNode = _nodes[parentIndex];
+
+ if (parentIndex > 0 && HasHigherPriority(node, parentNode))
+ {
+ CascadeUp(node);
+ }
+ else
+ {
+ //Note that CascadeDown will be called if parentNode == node (that is, node is the root)
+ CascadeDown(node);
+ }
+ }
+
+ /// <summary>
+ /// Removes a node from the queue. The node does not need to be the head of the queue.
+ /// If the node is not in the queue, the result is undefined. If unsure, check Contains() first
+ /// O(log n)
+ /// </summary>
+ public void Remove(TItem node)
+ {
+#if DEBUG
+ if (node == null)
+ {
+ throw new ArgumentNullException("node");
+ }
+ if (!Contains(node))
+ {
+ throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + node);
+ }
+#endif
+
+ //If the node is already the last node, we can remove it immediately
+ if (node.QueueIndex == _numNodes)
+ {
+ _nodes[_numNodes] = null;
+ _numNodes--;
+ return;
+ }
+
+ //Swap the node with the last node
+ TItem formerLastNode = _nodes[_numNodes];
+ Swap(node, formerLastNode);
+ _nodes[_numNodes] = null;
+ _numNodes--;
+
+ //Now bubble formerLastNode (which is no longer the last node) up or down as appropriate
+ OnNodeUpdated(formerLastNode);
+ }
+
+ public IEnumerator<TItem> GetEnumerator()
+ {
+ for (int i = 1; i <= _numNodes; i++)
+ yield return _nodes[i];
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ /// <summary>
+ /// <b>Should not be called in production code.</b>
+ /// Checks to make sure the queue is still in a valid state. Used for testing/debugging the queue.
+ /// </summary>
+ public bool IsValidQueue()
+ {
+ for (int i = 1; i < _nodes.Length; i++)
+ {
+ if (_nodes[i] != null)
+ {
+ int childLeftIndex = 2 * i;
+ if (childLeftIndex < _nodes.Length && _nodes[childLeftIndex] != null && HasHigherPriority(_nodes[childLeftIndex], _nodes[i]))
+ return false;
+
+ int childRightIndex = childLeftIndex + 1;
+ if (childRightIndex < _nodes.Length && _nodes[childRightIndex] != null && HasHigherPriority(_nodes[childRightIndex], _nodes[i]))
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs b/MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs
new file mode 100644
index 000000000..e6e93e443
--- /dev/null
+++ b/MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Priority_Queue
+{
+ /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
+ public class GenericPriorityQueueNode<TPriority>
+ {
+ /// <summary>
+ /// The Priority to insert this node at. Must be set BEFORE adding a node to the queue (ideally just once, in the node's constructor).
+ /// Should not be manually edited once the node has been enqueued - use queue.UpdatePriority() instead
+ /// </summary>
+ public TPriority Priority { get; protected internal set; }
+
+ /// <summary>
+ /// Represents the current position in the queue
+ /// </summary>
+ public int QueueIndex { get; internal set; }
+
+ /// <summary>
+ /// Represents the order the node was inserted in
+ /// </summary>
+ public long InsertionIndex { get; internal set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs b/MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs
new file mode 100644
index 000000000..8da88e1c6
--- /dev/null
+++ b/MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Priority_Queue
+{
+ /// <summary>
+ /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
+ /// A helper-interface only needed to make writing unit tests a bit easier (hence the 'internal' access modifier)
+ /// </summary>
+ internal interface IFixedSizePriorityQueue<TItem, in TPriority> : IPriorityQueue<TItem, TPriority>
+ where TPriority : IComparable<TPriority>
+ {
+ /// <summary>
+ /// Resize the queue so it can accept more nodes. All currently enqueued nodes are remain.
+ /// Attempting to decrease the queue size to a size too small to hold the existing nodes results in undefined behavior
+ /// </summary>
+ void Resize(int maxNodes);
+
+ /// <summary>
+ /// Returns the maximum number of items that can be enqueued at once in this queue. Once you hit this number (ie. once Count == MaxSize),
+ /// attempting to enqueue another item will cause undefined behavior.
+ /// </summary>
+ int MaxSize { get; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Providers/Manager/IPriorityQueue.cs b/MediaBrowser.Providers/Manager/IPriorityQueue.cs
new file mode 100644
index 000000000..425992b18
--- /dev/null
+++ b/MediaBrowser.Providers/Manager/IPriorityQueue.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Priority_Queue
+{
+ /// <summary>
+ /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
+ /// The IPriorityQueue interface. This is mainly here for purists, and in case I decide to add more implementations later.
+ /// For speed purposes, it is actually recommended that you *don't* access the priority queue through this interface, since the JIT can
+ /// (theoretically?) optimize method calls from concrete-types slightly better.
+ /// </summary>
+ public interface IPriorityQueue<TItem, in TPriority> : IEnumerable<TItem>
+ where TPriority : IComparable<TPriority>
+ {
+ /// <summary>
+ /// Enqueue a node to the priority queue. Lower values are placed in front. Ties are broken by first-in-first-out.
+ /// See implementation for how duplicates are handled.
+ /// </summary>
+ void Enqueue(TItem node, TPriority priority);
+
+ /// <summary>
+ /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it.
+ /// </summary>
+ bool TryDequeue(out TItem item);
+
+ /// <summary>
+ /// Removes every node from the queue.
+ /// </summary>
+ void Clear();
+
+ /// <summary>
+ /// Returns whether the given node is in the queue.
+ /// </summary>
+ bool Contains(TItem node);
+
+ /// <summary>
+ /// Removes a node from the queue. The node does not need to be the head of the queue.
+ /// </summary>
+ void Remove(TItem node);
+
+ /// <summary>
+ /// Call this method to change the priority of a node.
+ /// </summary>
+ void UpdatePriority(TItem node, TPriority priority);
+
+ /// <summary>
+ /// Returns the head of the queue, without removing it (use Dequeue() for that).
+ /// </summary>
+ TItem First { get; }
+
+ /// <summary>
+ /// Returns the number of nodes in the queue.
+ /// </summary>
+ int Count { get; }
+ }
+}
diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs
index 7c797133f..1d8275c26 100644
--- a/MediaBrowser.Providers/Manager/ImageSaver.cs
+++ b/MediaBrowser.Providers/Manager/ImageSaver.cs
@@ -238,7 +238,7 @@ namespace MediaBrowser.Providers.Manager
{
_logger.Debug("Saving image to {0}", path);
- var parentFolder = Path.GetDirectoryName(path);
+ var parentFolder = _fileSystem.GetDirectoryName(path);
await _imageSaveSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
@@ -247,7 +247,7 @@ namespace MediaBrowser.Providers.Manager
_libraryMonitor.ReportFileSystemChangeBeginning(path);
_libraryMonitor.ReportFileSystemChangeBeginning(parentFolder);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
// If the file is currently hidden we'll have to remove that or the save will fail
var file = _fileSystem.GetFileInfo(path);
@@ -449,7 +449,7 @@ namespace MediaBrowser.Providers.Manager
{
if (type == ImageType.Primary && item is Episode)
{
- path = Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename + extension);
+ path = Path.Combine(_fileSystem.GetDirectoryName(item.Path), "metadata", filename + extension);
}
else if (item.DetectIsInMixedFolder())
@@ -581,7 +581,7 @@ namespace MediaBrowser.Providers.Manager
if (item is Episode)
{
- var seasonFolder = Path.GetDirectoryName(item.Path);
+ var seasonFolder = _fileSystem.GetDirectoryName(item.Path);
var imageFilename = _fileSystem.GetFileNameWithoutExtension(item.Path) + "-thumb" + extension;
@@ -629,7 +629,7 @@ namespace MediaBrowser.Providers.Manager
{
imageFilename = "poster";
}
- var folder = Path.GetDirectoryName(item.Path);
+ var folder = _fileSystem.GetDirectoryName(item.Path);
return Path.Combine(folder, _fileSystem.GetFileNameWithoutExtension(item.Path) + "-" + imageFilename + extension);
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 0b8dca2eb..7ff018c7b 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -24,6 +24,7 @@ using MediaBrowser.Common.IO;
using MediaBrowser.Controller.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
+using Priority_Queue;
namespace MediaBrowser.Providers.Manager
{
@@ -577,7 +578,6 @@ 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>
@@ -607,8 +607,6 @@ namespace MediaBrowser.Providers.Manager
continue;
}
- await _saveLock.WaitAsync().ConfigureAwait(false);
-
try
{
_libraryMonitor.ReportFileSystemChangeBeginning(path);
@@ -620,7 +618,6 @@ namespace MediaBrowser.Providers.Manager
}
finally
{
- _saveLock.Release();
_libraryMonitor.ReportFileSystemChangeComplete(path, false);
}
}
@@ -851,20 +848,20 @@ namespace MediaBrowser.Providers.Manager
});
}
- private readonly ConcurrentQueue<Tuple<Guid, MetadataRefreshOptions>> _refreshQueue =
- new ConcurrentQueue<Tuple<Guid, MetadataRefreshOptions>>();
+ private readonly SimplePriorityQueue<Tuple<Guid, MetadataRefreshOptions>> _refreshQueue =
+ new SimplePriorityQueue<Tuple<Guid, MetadataRefreshOptions>>();
private readonly object _refreshQueueLock = new object();
private bool _isProcessingRefreshQueue;
- public void QueueRefresh(Guid id, MetadataRefreshOptions options)
+ public void QueueRefresh(Guid id, MetadataRefreshOptions options, RefreshPriority priority)
{
if (_disposed)
{
return;
}
- _refreshQueue.Enqueue(new Tuple<Guid, MetadataRefreshOptions>(id, options));
+ _refreshQueue.Enqueue(new Tuple<Guid, MetadataRefreshOptions>(id, options), (int)priority);
lock (_refreshQueueLock)
{
diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs
index 34cf63350..f544c09dc 100644
--- a/MediaBrowser.Providers/Manager/ProviderUtils.cs
+++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs
@@ -4,6 +4,8 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
+using System.Linq;
+using MediaBrowser.Controller.Extensions;
namespace MediaBrowser.Providers.Manager
{
@@ -89,11 +91,6 @@ namespace MediaBrowser.Providers.Manager
}
}
- if (replaceData || string.IsNullOrEmpty(target.OfficialRatingDescription))
- {
- target.OfficialRatingDescription = source.OfficialRatingDescription;
- }
-
if (replaceData || string.IsNullOrEmpty(target.CustomRating))
{
target.CustomRating = source.CustomRating;
@@ -122,6 +119,11 @@ namespace MediaBrowser.Providers.Manager
if (replaceData || targetResult.People == null || targetResult.People.Count == 0)
{
targetResult.People = sourceResult.People;
+
+ }
+ else if (targetResult.People != null && sourceResult.People != null)
+ {
+ MergePeople(sourceResult.People, targetResult.People);
}
}
@@ -205,6 +207,31 @@ namespace MediaBrowser.Providers.Manager
}
}
+ private static void MergePeople(List<PersonInfo> source, List<PersonInfo> target)
+ {
+ foreach (var person in target)
+ {
+ var normalizedName = person.Name.RemoveDiacritics();
+ var personInSource = source.FirstOrDefault(i => string.Equals(i.Name.RemoveDiacritics(), normalizedName, StringComparison.OrdinalIgnoreCase));
+
+ if (personInSource != null)
+ {
+ foreach (var providerId in personInSource.ProviderIds)
+ {
+ if (!person.ProviderIds.ContainsKey(providerId.Key))
+ {
+ person.ProviderIds[providerId.Key] = providerId.Value;
+ }
+ }
+
+ if (string.IsNullOrWhiteSpace(person.ImageUrl))
+ {
+ person.ImageUrl = personInSource.ImageUrl;
+ }
+ }
+ }
+ }
+
public static void MergeMetadataSettings(BaseItem source,
BaseItem target)
{
@@ -265,11 +292,6 @@ namespace MediaBrowser.Providers.Manager
{
target.CriticRating = source.CriticRating;
}
-
- if (replaceData || string.IsNullOrEmpty(target.CriticRatingSummary))
- {
- target.CriticRatingSummary = source.CriticRatingSummary;
- }
}
private static void MergeTrailers(BaseItem source, BaseItem target, List<MetadataFields> lockedFields, bool replaceData)
diff --git a/MediaBrowser.Providers/Manager/SimplePriorityQueue.cs b/MediaBrowser.Providers/Manager/SimplePriorityQueue.cs
new file mode 100644
index 000000000..f4c261a81
--- /dev/null
+++ b/MediaBrowser.Providers/Manager/SimplePriorityQueue.cs
@@ -0,0 +1,251 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Priority_Queue
+{
+ /// <summary>
+ /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp
+ /// A simplified priority queue implementation. Is stable, auto-resizes, and thread-safe, at the cost of being slightly slower than
+ /// FastPriorityQueue
+ /// </summary>
+ /// <typeparam name="TItem">The type to enqueue</typeparam>
+ /// <typeparam name="TPriority">The priority-type to use for nodes. Must extend IComparable&lt;TPriority&gt;</typeparam>
+ public class SimplePriorityQueue<TItem, TPriority> : IPriorityQueue<TItem, TPriority>
+ where TPriority : IComparable<TPriority>
+ {
+ private class SimpleNode : GenericPriorityQueueNode<TPriority>
+ {
+ public TItem Data { get; private set; }
+
+ public SimpleNode(TItem data)
+ {
+ Data = data;
+ }
+ }
+
+ private const int INITIAL_QUEUE_SIZE = 10;
+ private readonly GenericPriorityQueue<SimpleNode, TPriority> _queue;
+
+ public SimplePriorityQueue()
+ {
+ _queue = new GenericPriorityQueue<SimpleNode, TPriority>(INITIAL_QUEUE_SIZE);
+ }
+
+ /// <summary>
+ /// Given an item of type T, returns the exist SimpleNode in the queue
+ /// </summary>
+ private SimpleNode GetExistingNode(TItem item)
+ {
+ var comparer = EqualityComparer<TItem>.Default;
+ foreach (var node in _queue)
+ {
+ if (comparer.Equals(node.Data, item))
+ {
+ return node;
+ }
+ }
+ throw new InvalidOperationException("Item cannot be found in queue: " + item);
+ }
+
+ /// <summary>
+ /// Returns the number of nodes in the queue.
+ /// O(1)
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ lock (_queue)
+ {
+ return _queue.Count;
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Returns the head of the queue, without removing it (use Dequeue() for that).
+ /// Throws an exception when the queue is empty.
+ /// O(1)
+ /// </summary>
+ public TItem First
+ {
+ get
+ {
+ lock (_queue)
+ {
+ if (_queue.Count <= 0)
+ {
+ throw new InvalidOperationException("Cannot call .First on an empty queue");
+ }
+
+ SimpleNode first = _queue.First;
+ return (first != null ? first.Data : default(TItem));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Removes every node from the queue.
+ /// O(n)
+ /// </summary>
+ public void Clear()
+ {
+ lock (_queue)
+ {
+ _queue.Clear();
+ }
+ }
+
+ /// <summary>
+ /// Returns whether the given item is in the queue.
+ /// O(n)
+ /// </summary>
+ public bool Contains(TItem item)
+ {
+ lock (_queue)
+ {
+ var comparer = EqualityComparer<TItem>.Default;
+ foreach (var node in _queue)
+ {
+ if (comparer.Equals(node.Data, item))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it.
+ /// If queue is empty, throws an exception
+ /// O(log n)
+ /// </summary>
+ public bool TryDequeue(out TItem item)
+ {
+ lock (_queue)
+ {
+ if (_queue.Count <= 0)
+ {
+ item = default(TItem);
+ return false;
+ }
+
+ SimpleNode node;
+ if (_queue.TryDequeue(out node))
+ {
+ item = node.Data;
+ return true;
+ }
+
+ item = default(TItem);
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Enqueue a node to the priority queue. Lower values are placed in front. Ties are broken by first-in-first-out.
+ /// This queue automatically resizes itself, so there's no concern of the queue becoming 'full'.
+ /// Duplicates are allowed.
+ /// O(log n)
+ /// </summary>
+ public void Enqueue(TItem item, TPriority priority)
+ {
+ lock (_queue)
+ {
+ SimpleNode node = new SimpleNode(item);
+ if (_queue.Count == _queue.MaxSize)
+ {
+ _queue.Resize(_queue.MaxSize * 2 + 1);
+ }
+ _queue.Enqueue(node, priority);
+ }
+ }
+
+ /// <summary>
+ /// Removes an item from the queue. The item does not need to be the head of the queue.
+ /// If the item is not in the queue, an exception is thrown. If unsure, check Contains() first.
+ /// If multiple copies of the item are enqueued, only the first one is removed.
+ /// O(n)
+ /// </summary>
+ public void Remove(TItem item)
+ {
+ lock (_queue)
+ {
+ try
+ {
+ _queue.Remove(GetExistingNode(item));
+ }
+ catch (InvalidOperationException ex)
+ {
+ throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item, ex);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Call this method to change the priority of an item.
+ /// Calling this method on a item not in the queue will throw an exception.
+ /// If the item is enqueued multiple times, only the first one will be updated.
+ /// (If your requirements are complex enough that you need to enqueue the same item multiple times <i>and</i> be able
+ /// to update all of them, please wrap your items in a wrapper class so they can be distinguished).
+ /// O(n)
+ /// </summary>
+ public void UpdatePriority(TItem item, TPriority priority)
+ {
+ lock (_queue)
+ {
+ try
+ {
+ SimpleNode updateMe = GetExistingNode(item);
+ _queue.UpdatePriority(updateMe, priority);
+ }
+ catch (InvalidOperationException ex)
+ {
+ throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + item, ex);
+ }
+ }
+ }
+
+ public IEnumerator<TItem> GetEnumerator()
+ {
+ List<TItem> queueData = new List<TItem>();
+ lock (_queue)
+ {
+ //Copy to a separate list because we don't want to 'yield return' inside a lock
+ foreach (var node in _queue)
+ {
+ queueData.Add(node.Data);
+ }
+ }
+
+ return queueData.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public bool IsValidQueue()
+ {
+ lock (_queue)
+ {
+ return _queue.IsValidQueue();
+ }
+ }
+ }
+
+ /// <summary>
+ /// A simplified priority queue implementation. Is stable, auto-resizes, and thread-safe, at the cost of being slightly slower than
+ /// FastPriorityQueue
+ /// This class is kept here for backwards compatibility. It's recommended you use Simple
+ /// </summary>
+ /// <typeparam name="TItem">The type to enqueue</typeparam>
+ public class SimplePriorityQueue<TItem> : SimplePriorityQueue<TItem, float> { }
+} \ No newline at end of file
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index fe554545f..9d20ec423 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -65,10 +65,15 @@
<Compile Include="LiveTv\ChannelMetadataService.cs" />
<Compile Include="LiveTv\ProgramMetadataService.cs" />
<Compile Include="LiveTv\VideoRecordingService.cs" />
+ <Compile Include="Manager\GenericPriorityQueue.cs" />
+ <Compile Include="Manager\GenericPriorityQueueNode.cs" />
+ <Compile Include="Manager\IFixedSizePriorityQueue.cs" />
<Compile Include="Manager\ImageSaver.cs" />
+ <Compile Include="Manager\IPriorityQueue.cs" />
<Compile Include="Manager\ItemImageProvider.cs" />
<Compile Include="Manager\ProviderManager.cs" />
<Compile Include="Manager\MetadataService.cs" />
+ <Compile Include="Manager\SimplePriorityQueue.cs" />
<Compile Include="MediaInfo\FFProbeAudioInfo.cs" />
<Compile Include="MediaInfo\FFProbeProvider.cs" />
<Compile Include="MediaInfo\FFProbeVideoInfo.cs" />
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index d65084287..cc5e7aef9 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (!_fileSystem.FileExists(path))
{
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.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) ??
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
index afcf4b226..04e549526 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
@@ -78,7 +78,7 @@ namespace MediaBrowser.Providers.MediaInfo
}, cancellationToken).ConfigureAwait(false);
- //Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
+ //Directory.CreateDirectory(_fileSystem.GetDirectoryName(cachePath));
//_json.SerializeToFile(result, cachePath);
return result;
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index 0aaa56bab..c686e1d2e 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -150,7 +150,7 @@ namespace MediaBrowser.Providers.MediaInfo
}, cancellationToken).ConfigureAwait(false);
- //Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
+ //Directory.CreateDirectory(_fileSystem.GetDirectoryName(cachePath));
//_json.SerializeToFile(result, cachePath);
return result;
@@ -356,11 +356,6 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- if (!string.IsNullOrWhiteSpace(data.OfficialRatingDescription) || isFullRefresh)
- {
- video.OfficialRatingDescription = data.OfficialRatingDescription;
- }
-
if (!video.IsLocked && !video.LockedFields.Contains(MetadataFields.Genres))
{
if (video.Genres.Count == 0 || isFullRefresh)
diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
index dd2cad1f9..84d8d20ad 100644
--- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
+++ b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
@@ -277,14 +277,13 @@ namespace MediaBrowser.Providers.Movies
var path = GetFanartJsonPath(id);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
try
{
using (var response = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = FanartArtistProvider.Current.FanArtResourcePool,
CancellationToken = cancellationToken,
BufferContent = true
diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
index 0101478b8..670215479 100644
--- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
+++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
@@ -94,7 +94,7 @@ namespace MediaBrowser.Providers.Movies
tmdbId = movieInfo.id.ToString(_usCulture);
dataFilePath = MovieDbProvider.Current.GetDataFilePath(tmdbId, language);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(movieInfo, dataFilePath);
}
}
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index 8e4b86519..d6aef5d1c 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -30,8 +30,6 @@ namespace MediaBrowser.Providers.Movies
/// </summary>
public class MovieDbProvider : IRemoteMetadataProvider<Movie, MovieInfo>, IDisposable, IHasOrder
{
- internal readonly SemaphoreSlim MovieDbResourcePool = new SemaphoreSlim(1, 1);
-
internal static MovieDbProvider Current { get; private set; }
private readonly IJsonSerializer _jsonSerializer;
@@ -137,10 +135,6 @@ namespace MediaBrowser.Providers.Movies
/// <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)
- {
- MovieDbResourcePool.Dispose();
- }
}
/// <summary>
@@ -214,7 +208,7 @@ namespace MediaBrowser.Providers.Movies
var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
@@ -431,7 +425,6 @@ namespace MediaBrowser.Providers.Movies
await Task.Delay(Convert.ToInt32(delayMs)).ConfigureAwait(false);
}
- options.ResourcePool = MovieDbResourcePool;
_lastRequestTicks = DateTime.UtcNow.Ticks;
options.BufferContent = true;
diff --git a/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs b/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs
index 7abe9cc07..0cb1a7ff1 100644
--- a/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs
+++ b/MediaBrowser.Providers/Music/AlbumImageFromSongProvider.cs
@@ -20,8 +20,7 @@ namespace MediaBrowser.Providers.Music
{
var album = (MusicAlbum)item;
- var image = album.GetRecursiveChildren()
- .OfType<Audio>()
+ var image = album.GetRecursiveChildren(i => !i.IsFolder)
.Select(i => i.GetImageInfo(type, 0))
.FirstOrDefault(i => i != null && i.IsLocalFile);
diff --git a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
index 96eab63cd..6d9b20689 100644
--- a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
@@ -159,7 +159,7 @@ namespace MediaBrowser.Providers.Music
var path = GetAlbumInfoPath(_config.ApplicationPaths, musicBrainzReleaseGroupId);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
using (var response = await _httpClient.Get(new HttpRequestOptions
{
diff --git a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs
index 0f0c31e6e..c960e59a3 100644
--- a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs
@@ -27,7 +27,6 @@ namespace MediaBrowser.Providers.Music
public static AudioDbArtistProvider Current;
- public SemaphoreSlim AudioDbResourcePool = new SemaphoreSlim(2, 2);
private const string ApiKey = "49jhsf8248yfahka89724011";
public const string BaseUrl = "http://www.theaudiodb.com/api/v1/json/" + ApiKey;
@@ -151,13 +150,12 @@ namespace MediaBrowser.Providers.Music
using (var response = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = AudioDbResourcePool,
CancellationToken = cancellationToken,
BufferContent = true
}).ConfigureAwait(false))
{
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
using (var xmlFileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
index 6fd0d82bd..977f81414 100644
--- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
@@ -27,7 +27,6 @@ namespace MediaBrowser.Providers.Music
{
public class FanartArtistProvider : IRemoteImageProvider, IHasOrder
{
- internal readonly SemaphoreSlim FanArtResourcePool = new SemaphoreSlim(3, 3);
internal const string ApiKey = "5c6b04c68e904cfed1e6cbc9a9e683d4";
private const string FanArtBaseUrl = "https://webservice.fanart.tv/v3.1/music/{1}?api_key={0}";
@@ -248,14 +247,13 @@ namespace MediaBrowser.Providers.Music
var jsonPath = GetArtistJsonPath(_config.ApplicationPaths, musicBrainzId);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(jsonPath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(jsonPath));
try
{
using (var response = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = FanArtResourcePool,
CancellationToken = cancellationToken,
BufferContent = true
diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
index 4aefb62c8..b77fcf1b2 100644
--- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs
@@ -548,11 +548,6 @@ namespace MediaBrowser.Providers.Music
return null;
}
- /// <summary>
- /// The _music brainz resource pool
- /// </summary>
- private readonly SemaphoreSlim _musicBrainzResourcePool = new SemaphoreSlim(1, 1);
-
private long _lastMbzUrlQueryTicks = 0;
private List<MbzUrl> _mbzUrls = null;
private MbzUrl _chosenUrl;
@@ -656,7 +651,6 @@ namespace MediaBrowser.Providers.Music
Url = url,
CancellationToken = cancellationToken,
UserAgent = _appHost.Name + "/" + _appHost.ApplicationVersion,
- ResourcePool = _musicBrainzResourcePool,
BufferContent = throttleMs > 0
};
diff --git a/MediaBrowser.Providers/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Omdb/OmdbProvider.cs
index 2c368c97b..d1c3b2214 100644
--- a/MediaBrowser.Providers/Omdb/OmdbProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbProvider.cs
@@ -19,7 +19,6 @@ namespace MediaBrowser.Providers.Omdb
{
public class OmdbProvider
{
- internal static readonly SemaphoreSlim ResourcePool = new SemaphoreSlim(1, 1);
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _configurationManager;
@@ -104,17 +103,17 @@ namespace MediaBrowser.Providers.Omdb
ParseAdditionalMetadata(itemResult, result);
}
- public async Task<bool> FetchEpisodeData<T>(MetadataResult<T> itemResult, int episodeNumber, int seasonNumber, string imdbId, string language, string country, CancellationToken cancellationToken)
+ public async Task<bool> FetchEpisodeData<T>(MetadataResult<T> itemResult, int episodeNumber, int seasonNumber, string episodeImdbId, string seriesImdbId, string language, string country, CancellationToken cancellationToken)
where T : BaseItem
{
- if (string.IsNullOrWhiteSpace(imdbId))
+ if (string.IsNullOrWhiteSpace(seriesImdbId))
{
- throw new ArgumentNullException("imdbId");
+ throw new ArgumentNullException("seriesImdbId");
}
T item = itemResult.Item;
- var seasonResult = await GetSeasonRootObject(imdbId, seasonNumber, cancellationToken).ConfigureAwait(false);
+ var seasonResult = await GetSeasonRootObject(seriesImdbId, seasonNumber, cancellationToken).ConfigureAwait(false);
if (seasonResult == null)
{
@@ -123,12 +122,28 @@ namespace MediaBrowser.Providers.Omdb
RootObject result = null;
- foreach (var episode in (seasonResult.Episodes ?? new RootObject[] { }))
+ if (!string.IsNullOrWhiteSpace(episodeImdbId))
{
- if (episode.Episode == episodeNumber)
+ foreach (var episode in (seasonResult.Episodes ?? new RootObject[] { }))
{
- result = episode;
- break;
+ if (string.Equals(episodeImdbId, episode.imdbID, StringComparison.OrdinalIgnoreCase))
+ {
+ result = episode;
+ break;
+ }
+ }
+ }
+
+ // finally, search by numbers
+ if (result == null)
+ {
+ foreach (var episode in (seasonResult.Episodes ?? new RootObject[] { }))
+ {
+ if (episode.Episode == episodeNumber)
+ {
+ result = episode;
+ break;
+ }
}
}
@@ -283,7 +298,7 @@ namespace MediaBrowser.Providers.Omdb
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{
var rootObject = _jsonSerializer.DeserializeFromStream<RootObject>(stream);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(rootObject, path);
}
@@ -318,7 +333,7 @@ namespace MediaBrowser.Providers.Omdb
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{
var rootObject = _jsonSerializer.DeserializeFromStream<SeasonRootObject>(stream);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(rootObject, path);
}
@@ -330,7 +345,6 @@ namespace MediaBrowser.Providers.Omdb
return httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = ResourcePool,
CancellationToken = cancellationToken,
BufferContent = true,
EnableDefaultUserAgent = true
diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
index 3645a5f8d..19b8f292c 100644
--- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
+++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
@@ -250,7 +250,7 @@ namespace MediaBrowser.Providers.People
}).ConfigureAwait(false))
{
- _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
using (var fs = _fileSystem.GetFileStream(dataFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
{
diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs
index bf017d148..8579bd16b 100644
--- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs
+++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs
@@ -4,15 +4,12 @@ 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 MediaBrowser.Common.IO;
-using MediaBrowser.Controller.IO;
using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Studios
@@ -23,8 +20,6 @@ namespace MediaBrowser.Providers.Studios
private readonly IHttpClient _httpClient;
private readonly IFileSystem _fileSystem;
- private readonly SemaphoreSlim _listResourcePool = new SemaphoreSlim(1, 1);
-
public StudiosImageProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem)
{
_config = config;
@@ -69,7 +64,7 @@ namespace MediaBrowser.Providers.Studios
{
var posterPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotestudioposters.txt");
- await EnsurePosterList(posterPath, cancellationToken).ConfigureAwait(false);
+ posterPath = await EnsurePosterList(posterPath, cancellationToken).ConfigureAwait(false);
list.Add(GetImage(item, posterPath, ImageType.Primary, "folder"));
}
@@ -80,7 +75,7 @@ namespace MediaBrowser.Providers.Studios
{
var thumbsPath = Path.Combine(_config.ApplicationPaths.CachePath, "imagesbyname", "remotestudiothumbs.txt");
- await EnsureThumbsList(thumbsPath, cancellationToken).ConfigureAwait(false);
+ thumbsPath = await EnsureThumbsList(thumbsPath, cancellationToken).ConfigureAwait(false);
list.Add(GetImage(item, thumbsPath, ImageType.Thumb, "thumb"));
}
@@ -114,18 +109,18 @@ namespace MediaBrowser.Providers.Studios
return string.Format("https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/studios/{0}/{1}.jpg", image, filename);
}
- private Task EnsureThumbsList(string file, CancellationToken cancellationToken)
+ private Task<string> EnsureThumbsList(string file, CancellationToken cancellationToken)
{
const string url = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/studiothumbs.txt";
- return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, _listResourcePool, cancellationToken);
+ return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, cancellationToken);
}
- private Task EnsurePosterList(string file, CancellationToken cancellationToken)
+ private Task<string> EnsurePosterList(string file, CancellationToken cancellationToken)
{
const string url = "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/studioposters.txt";
- return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, _listResourcePool, cancellationToken);
+ return ImageUtils.EnsureList(url, file, _httpClient, _fileSystem, cancellationToken);
}
public int Order
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
index cd741bed5..1cf965e02 100644
--- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -115,7 +115,7 @@ namespace MediaBrowser.Providers.Subtitles
using (var stream = response.Stream)
{
- var savePath = Path.Combine(Path.GetDirectoryName(video.Path),
+ var savePath = Path.Combine(_fileSystem.GetDirectoryName(video.Path),
_fileSystem.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower());
if (response.IsForced)
@@ -256,12 +256,7 @@ namespace MediaBrowser.Providers.Subtitles
_monitor.ReportFileSystemChangeComplete(path, false);
}
- return _libraryManager.GetItemById(itemId).RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_logger, _fileSystem))
- {
- ImageRefreshMode = ImageRefreshMode.ValidationOnly,
- MetadataRefreshMode = MetadataRefreshMode.ValidationOnly
-
- }, CancellationToken.None);
+ return _libraryManager.GetItemById(itemId).ChangedExternally();
}
public Task<SubtitleResponse> GetRemoteSubtitles(string id, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs
index fd4d041b2..279447a18 100644
--- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs
@@ -53,8 +53,8 @@ namespace MediaBrowser.Providers.TV
private async Task<bool> AddDummySeasonFolders(Series series, CancellationToken cancellationToken)
{
- var episodesInSeriesFolder = series.GetRecursiveChildren()
- .OfType<Episode>()
+ var episodesInSeriesFolder = series.GetRecursiveChildren(i => i is Episode)
+ .Cast<Episode>()
.Where(i => !i.IsInSeasonFolder)
.ToList();
@@ -125,8 +125,7 @@ namespace MediaBrowser.Providers.TV
Id = _libraryManager.GetNewItemId((series.Id + (seasonNumber ?? -1).ToString(_usCulture) + seasonName), typeof(Season)),
IsVirtualItem = isVirtualItem,
SeriesId = series.Id,
- SeriesName = series.Name,
- SeriesSortName = series.SortName
+ SeriesName = series.Name
};
season.SetParent(series);
diff --git a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
index 538d96c17..bef4d8815 100644
--- a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
+++ b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
@@ -27,13 +27,6 @@ namespace MediaBrowser.Providers.TV
updateType |= ItemUpdateType.MetadataImport;
}
- var seriesSortName = item.FindSeriesSortName();
- if (!string.Equals(item.SeriesSortName, seriesSortName, StringComparison.Ordinal))
- {
- item.SeriesSortName = seriesSortName;
- updateType |= ItemUpdateType.MetadataImport;
- }
-
var seasonName = item.FindSeasonName();
if (!string.Equals(item.SeasonName, seasonName, StringComparison.Ordinal))
{
diff --git a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs
index 8db3eaa79..35178e1fe 100644
--- a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs
@@ -312,14 +312,13 @@ namespace MediaBrowser.Providers.TV
var path = GetFanartJsonPath(tvdbId);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
try
{
using (var response = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = FanartArtistProvider.Current.FanArtResourcePool,
CancellationToken = cancellationToken,
BufferContent = true
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index d5154b1d3..5b9e5d5eb 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -203,7 +203,7 @@ namespace MediaBrowser.Providers.TV
CancellationToken cancellationToken)
{
var existingEpisodes = (from s in series
- from c in s.GetRecursiveChildren().OfType<Episode>()
+ from c in s.GetRecursiveChildren(i => i is Episode).Cast<Episode>()
select new Tuple<int, Episode>((c.ParentIndexNumber ?? 0) , c))
.ToList();
@@ -275,13 +275,16 @@ namespace MediaBrowser.Providers.TV
return hasChanges;
}
- private Series DetermineAppropriateSeries(IEnumerable<Series> series, int seasonNumber)
+ private Series DetermineAppropriateSeries(List<Series> series, int seasonNumber)
{
- var seriesAndOffsets = series.ToList();
+ if (series.Count == 1)
+ {
+ return series[0];
+ }
- return seriesAndOffsets.FirstOrDefault(s => s.GetRecursiveChildren().OfType<Season>().Any(season => (season.IndexNumber) == seasonNumber)) ??
- seriesAndOffsets.FirstOrDefault(s => s.GetRecursiveChildren().OfType<Season>().Any(season => (season.IndexNumber) == 1)) ??
- seriesAndOffsets.OrderBy(s => s.GetRecursiveChildren().OfType<Season>().Select(season => season.IndexNumber).Min()).First();
+ return series.FirstOrDefault(s => s.GetRecursiveChildren(i => i is Season).Any(season => (season.IndexNumber) == seasonNumber)) ??
+ series.FirstOrDefault(s => s.GetRecursiveChildren(i => i is Season).Any(season => (season.IndexNumber) == 1)) ??
+ series.OrderBy(s => s.GetRecursiveChildren(i => i is Season).Select(season => season.IndexNumber).Min()).First();
}
/// <summary>
@@ -292,7 +295,7 @@ namespace MediaBrowser.Providers.TV
bool allowMissingEpisodes)
{
var existingEpisodes = (from s in series
- from c in s.GetRecursiveChildren().OfType<Episode>()
+ from c in s.GetRecursiveChildren(i => i is Episode).Cast<Episode>()
select new { Episode = c })
.ToList();
@@ -402,7 +405,7 @@ namespace MediaBrowser.Providers.TV
// Season does not have a number
// Remove if there are no episodes directly in series without a season number
- return i.Series.GetRecursiveChildren().OfType<Episode>().All(s => s.ParentIndexNumber.HasValue || s.IsInSeasonFolder);
+ return i.Series.GetRecursiveChildren(e => e is Episode).Cast<Episode>().All(s => s.ParentIndexNumber.HasValue || s.IsInSeasonFolder);
})
.ToList();
diff --git a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs
index 56aa3967c..f73244cdf 100644
--- a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs
@@ -58,11 +58,10 @@ namespace MediaBrowser.Providers.TV
string seriesImdbId;
if (info.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out seriesImdbId) && !string.IsNullOrEmpty(seriesImdbId))
{
- if (info.IndexNumber.HasValue &&
- info.ParentIndexNumber.HasValue)
+ if (info.IndexNumber.HasValue && info.ParentIndexNumber.HasValue)
{
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);
+ .FetchEpisodeData(result, info.IndexNumber.Value, info.ParentIndexNumber.Value, info.GetProviderId(MetadataProviders.Imdb), seriesImdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
}
}
diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
index af7dea59e..74c8b4ec3 100644
--- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
@@ -44,13 +44,6 @@ namespace MediaBrowser.Providers.TV
updateType |= ItemUpdateType.MetadataImport;
}
- 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))
{
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs
index 38831feb6..b2d70918c 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs
@@ -106,7 +106,7 @@ namespace MediaBrowser.Providers.TV
var dataFilePath = GetDataFilePath(id, seasonNumber, episodeNumber, preferredMetadataLanguage);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
@@ -142,8 +142,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/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs
index 1f0cc9e52..f41e254ca 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs
@@ -190,7 +190,7 @@ namespace MediaBrowser.Providers.TV
var dataFilePath = GetDataFilePath(id, seasonNumber, preferredMetadataLanguage);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs
index 5b4ae9745..f29024737 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs
@@ -198,7 +198,7 @@ namespace MediaBrowser.Providers.TV
tmdbId = seriesInfo.id.ToString(_usCulture);
dataFilePath = GetDataFilePath(tmdbId, language);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(seriesInfo, dataFilePath);
await EnsureSeriesInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
@@ -330,7 +330,7 @@ namespace MediaBrowser.Providers.TV
var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs
index 989748846..030150e4d 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs
@@ -175,8 +175,7 @@ namespace MediaBrowser.Providers.TV
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs
index 4a52b972f..24c2b507a 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs
@@ -226,7 +226,7 @@ namespace MediaBrowser.Providers.TV
if (searchInfo.IndexNumber.HasValue)
{
- var files = GetEpisodeXmlFiles(searchInfo.ParentIndexNumber, searchInfo.IndexNumber, searchInfo.IndexNumberEnd, Path.GetDirectoryName(xmlFile));
+ var files = GetEpisodeXmlFiles(searchInfo.ParentIndexNumber, searchInfo.IndexNumber, searchInfo.IndexNumberEnd, _fileSystem.GetDirectoryName(xmlFile));
list = files.Select(GetXmlReader).ToList();
}
@@ -919,8 +919,7 @@ namespace MediaBrowser.Providers.TV
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
+ Url = url
});
}
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs
index 72bd62d9f..e8ed05225 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs
@@ -143,7 +143,6 @@ namespace MediaBrowser.Providers.TV
Url = ServerTimeUrl,
CancellationToken = cancellationToken,
EnableHttpCompression = true,
- ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool,
BufferContent = false
}).ConfigureAwait(false))
@@ -240,7 +239,6 @@ namespace MediaBrowser.Providers.TV
Url = string.Format(UpdatesUrl, lastUpdateTime),
CancellationToken = cancellationToken,
EnableHttpCompression = true,
- ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool,
BufferContent = false
}).ConfigureAwait(false))
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs
index e68b7ad1d..daa6e78f5 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs
@@ -358,8 +358,7 @@ namespace MediaBrowser.Providers.TV
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs
index cdb9ac51e..50bc6bc74 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs
@@ -347,8 +347,7 @@ namespace MediaBrowser.Providers.TV
return _httpClient.GetResponse(new HttpRequestOptions
{
CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = TvdbSeriesProvider.Current.TvDbResourcePool
+ Url = url
});
}
}
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
index af37c7632..4c5e57a94 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
@@ -27,7 +27,6 @@ namespace MediaBrowser.Providers.TV
{
public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder
{
- internal readonly SemaphoreSlim TvDbResourcePool = new SemaphoreSlim(2, 2);
internal static TvdbSeriesProvider Current { get; private set; }
private readonly IZipClient _zipClient;
private readonly IHttpClient _httpClient;
@@ -220,7 +219,6 @@ namespace MediaBrowser.Providers.TV
using (var zipStream = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = TvDbResourcePool,
CancellationToken = cancellationToken,
BufferContent = false
@@ -265,7 +263,6 @@ namespace MediaBrowser.Providers.TV
using (var result = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = TvDbResourcePool,
CancellationToken = cancellationToken,
BufferContent = false
@@ -520,7 +517,6 @@ namespace MediaBrowser.Providers.TV
using (var stream = await _httpClient.Get(new HttpRequestOptions
{
Url = url,
- ResourcePool = TvDbResourcePool,
CancellationToken = cancellationToken,
BufferContent = false
@@ -1651,7 +1647,6 @@ namespace MediaBrowser.Providers.TV
{
CancellationToken = cancellationToken,
Url = url,
- ResourcePool = TvDbResourcePool,
BufferContent = false
});
}
diff --git a/MediaBrowser.Server.Mac.sln b/MediaBrowser.Server.Mac.sln
index 037cd488b..bc7cba21f 100644
--- a/MediaBrowser.Server.Mac.sln
+++ b/MediaBrowser.Server.Mac.sln
@@ -37,8 +37,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DvdLib", "DvdLib\DvdLib.csp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Dlna", "Emby.Dlna\Emby.Dlna.csproj", "{805844AB-E92F-45E6-9D99-4F6D48D129A5}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing.ImageMagick", "Emby.Drawing.ImageMagick\Emby.Drawing.ImageMagick.csproj", "{6CFEE013-6E7C-432B-AC37-CABF0880C69A}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing.Net", "Emby.Drawing.Net\Emby.Drawing.Net.csproj", "{C97A239E-A96C-4D64-A844-CCF8CC30AECB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Photos", "Emby.Photos\Emby.Photos.csproj", "{89AB4548-770D-41FD-A891-8DAFF44F452C}"
@@ -400,26 +398,6 @@ Global
{805844AB-E92F-45E6-9D99-4F6D48D129A5}.Signed|Any CPU.Build.0 = Release|Any CPU
{805844AB-E92F-45E6-9D99-4F6D48D129A5}.Signed|x86.ActiveCfg = Release|Any CPU
{805844AB-E92F-45E6-9D99-4F6D48D129A5}.Signed|x86.Build.0 = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.AppStore|Any CPU.Build.0 = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.AppStore|x86.ActiveCfg = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.AppStore|x86.Build.0 = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|x86.ActiveCfg = Debug|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|x86.Build.0 = Debug|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release Mono|Any CPU.Build.0 = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release Mono|x86.ActiveCfg = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release Mono|x86.Build.0 = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|Any CPU.Build.0 = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|x86.ActiveCfg = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|x86.Build.0 = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Signed|Any CPU.ActiveCfg = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Signed|Any CPU.Build.0 = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Signed|x86.ActiveCfg = Release|Any CPU
- {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Signed|x86.Build.0 = Release|Any CPU
{C97A239E-A96C-4D64-A844-CCF8CC30AECB}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{C97A239E-A96C-4D64-A844-CCF8CC30AECB}.AppStore|Any CPU.Build.0 = Release|Any CPU
{C97A239E-A96C-4D64-A844-CCF8CC30AECB}.AppStore|x86.ActiveCfg = Release|Any CPU
diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
index 0cf488bd0..8133efafb 100644
--- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
+++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
@@ -162,9 +162,6 @@
<ItemGroup>
<None Include="Info.plist" />
<None Include="packages.config" />
- <None Include="ImageMagickSharp.dll.config">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </None>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
@@ -338,18 +335,6 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\gamegenres.html">
<Link>Resources\dashboard-ui\gamegenres.html</Link>
</BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\games.html">
- <Link>Resources\dashboard-ui\games.html</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\gamesrecommended.html">
- <Link>Resources\dashboard-ui\gamesrecommended.html</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\gamestudios.html">
- <Link>Resources\dashboard-ui\gamestudios.html</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\gamesystems.html">
- <Link>Resources\dashboard-ui\gamesystems.html</Link>
- </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\home.html">
<Link>Resources\dashboard-ui\home.html</Link>
</BundleResource>
@@ -953,84 +938,6 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\material-icons\style.css">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\material-icons\style.css</Link>
</BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\-l14jk06m6puhb-5mxqqnrjtnkitppoi_ivcxxdnrsc.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\-l14jk06m6puhb-5mxqqnrjtnkitppoi_ivcxxdnrsc.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\0ec6fl06luxeywpbsjvxcbjtnkitppoi_ivcxxdnrsc.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\0ec6fl06luxeywpbsjvxcbjtnkitppoi_ivcxxdnrsc.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\2tsd397wlxj96qwhynikxpeszw2xoq-xsnqo47m55da.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\2tsd397wlxj96qwhynikxpeszw2xoq-xsnqo47m55da.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\97uahxiqzroncbacei3awxjtnkitppoi_ivcxxdnrsc.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\97uahxiqzroncbacei3awxjtnkitppoi_ivcxxdnrsc.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\azmswpodyevhtrvuabjwvbtbgvql8ndjpwnre27mub0.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\azmswpodyevhtrvuabjwvbtbgvql8ndjpwnre27mub0.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\cwb0xya8bzo0ksthx0utua.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\cwb0xya8bzo0ksthx0utua.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\d-6iyplofoccackzxwxsoftxra8tvwticgirnjhmvjw.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\d-6iyplofoccackzxwxsoftxra8tvwticgirnjhmvjw.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\e7mevayvogmqfwwl61pkhbtbgvql8ndjpwnre27mub0.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\e7mevayvogmqfwwl61pkhbtbgvql8ndjpwnre27mub0.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\fcx7wwv8ozt71a3e1xoajveszw2xoq-xsnqo47m55da.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\fcx7wwv8ozt71a3e1xoajveszw2xoq-xsnqo47m55da.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\fl4y0qdoxyythegmxx8kcrjtnkitppoi_ivcxxdnrsc.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\fl4y0qdoxyythegmxx8kcrjtnkitppoi_ivcxxdnrsc.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\frnv30oaydlfrth2vnzzdhtbgvql8ndjpwnre27mub0.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\frnv30oaydlfrth2vnzzdhtbgvql8ndjpwnre27mub0.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\gwvjdern2amz39wrsoz7fxtbgvql8ndjpwnre27mub0.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\gwvjdern2amz39wrsoz7fxtbgvql8ndjpwnre27mub0.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\hgo13k-tfspn0qi1sfdufvtxra8tvwticgirnjhmvjw.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\hgo13k-tfspn0qi1sfdufvtxra8tvwticgirnjhmvjw.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\i3s1wsgsg9ycurv6puktorjtnkitppoi_ivcxxdnrsc.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\i3s1wsgsg9ycurv6puktorjtnkitppoi_ivcxxdnrsc.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\nydwbdd4giq26g5xybhsfbjtnkitppoi_ivcxxdnrsc.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\nydwbdd4giq26g5xybhsfbjtnkitppoi_ivcxxdnrsc.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\ooefwznlrtefzlymlvv1ubjtnkitppoi_ivcxxdnrsc.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\ooefwznlrtefzlymlvv1ubjtnkitppoi_ivcxxdnrsc.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\pru33qjshpzsmg3z6vywnrjtnkitppoi_ivcxxdnrsc.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\pru33qjshpzsmg3z6vywnrjtnkitppoi_ivcxxdnrsc.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\robotobold.woff">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\robotobold.woff</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\robotolight.woff">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\robotolight.woff</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\robotomedium.woff">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\robotomedium.woff</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\robotoregular.woff">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\robotoregular.woff</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\robotothin.woff">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\robotothin.woff</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\rxzjdnzeo3r5zsexge8uuvtxra8tvwticgirnjhmvjw.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\rxzjdnzeo3r5zsexge8uuvtxra8tvwticgirnjhmvjw.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\style.css">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\style.css</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\ty9dfvlaziwdqq2dhoyjphtbgvql8ndjpwnre27mub0.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\ty9dfvlaziwdqq2dhoyjphtbgvql8ndjpwnre27mub0.woff2</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\vvxugkzxbhtx_s_vctlpghtbgvql8ndjpwnre27mub0.woff2">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fonts\roboto\vvxugkzxbhtx_s_vctlpghtbgvql8ndjpwnre27mub0.woff2</Link>
- </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\fullscreen\fullscreen-doubleclick.js">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\fullscreen\fullscreen-doubleclick.js</Link>
</BundleResource>
@@ -1061,9 +968,6 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\headroom\headroom.js">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\headroom\headroom.js</Link>
</BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\homescreensettings\homescreensettings.css">
- <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\homescreensettings\homescreensettings.css</Link>
- </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\homescreensettings\homescreensettings.js">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\homescreensettings\homescreensettings.js</Link>
</BundleResource>
@@ -1331,6 +1235,21 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\scroller\smoothscroller.js">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\scroller\smoothscroller.js</Link>
</BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\search\searchfields.css">
+ <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\search\searchfields.css</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\search\searchfields.js">
+ <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\search\searchfields.js</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\search\searchfields.template.html">
+ <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\search\searchfields.template.html</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\search\searchresults.js">
+ <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\search\searchresults.js</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\search\searchresults.template.html">
+ <Link>Resources\dashboard-ui\bower_components\emby-webcomponents\search\searchresults.template.html</Link>
+ </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\emby-webcomponents\serviceworker\notifications.js">
<Link>Resources\dashboard-ui\bower_components\emby-webcomponents\serviceworker\notifications.js</Link>
</BundleResource>
@@ -2162,6 +2081,84 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\files\dummy.mp4">
<Link>Resources\dashboard-ui\files\dummy.mp4</Link>
</BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\-l14jk06m6puhb-5mxqqnrjtnkitppoi_ivcxxdnrsc.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\-l14jk06m6puhb-5mxqqnrjtnkitppoi_ivcxxdnrsc.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\0ec6fl06luxeywpbsjvxcbjtnkitppoi_ivcxxdnrsc.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\0ec6fl06luxeywpbsjvxcbjtnkitppoi_ivcxxdnrsc.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\2tsd397wlxj96qwhynikxpeszw2xoq-xsnqo47m55da.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\2tsd397wlxj96qwhynikxpeszw2xoq-xsnqo47m55da.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\97uahxiqzroncbacei3awxjtnkitppoi_ivcxxdnrsc.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\97uahxiqzroncbacei3awxjtnkitppoi_ivcxxdnrsc.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\azmswpodyevhtrvuabjwvbtbgvql8ndjpwnre27mub0.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\azmswpodyevhtrvuabjwvbtbgvql8ndjpwnre27mub0.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\cwb0xya8bzo0ksthx0utua.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\cwb0xya8bzo0ksthx0utua.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\d-6iyplofoccackzxwxsoftxra8tvwticgirnjhmvjw.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\d-6iyplofoccackzxwxsoftxra8tvwticgirnjhmvjw.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\e7mevayvogmqfwwl61pkhbtbgvql8ndjpwnre27mub0.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\e7mevayvogmqfwwl61pkhbtbgvql8ndjpwnre27mub0.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\fcx7wwv8ozt71a3e1xoajveszw2xoq-xsnqo47m55da.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\fcx7wwv8ozt71a3e1xoajveszw2xoq-xsnqo47m55da.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\fl4y0qdoxyythegmxx8kcrjtnkitppoi_ivcxxdnrsc.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\fl4y0qdoxyythegmxx8kcrjtnkitppoi_ivcxxdnrsc.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\frnv30oaydlfrth2vnzzdhtbgvql8ndjpwnre27mub0.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\frnv30oaydlfrth2vnzzdhtbgvql8ndjpwnre27mub0.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\gwvjdern2amz39wrsoz7fxtbgvql8ndjpwnre27mub0.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\gwvjdern2amz39wrsoz7fxtbgvql8ndjpwnre27mub0.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\hgo13k-tfspn0qi1sfdufvtxra8tvwticgirnjhmvjw.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\hgo13k-tfspn0qi1sfdufvtxra8tvwticgirnjhmvjw.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\i3s1wsgsg9ycurv6puktorjtnkitppoi_ivcxxdnrsc.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\i3s1wsgsg9ycurv6puktorjtnkitppoi_ivcxxdnrsc.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\nydwbdd4giq26g5xybhsfbjtnkitppoi_ivcxxdnrsc.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\nydwbdd4giq26g5xybhsfbjtnkitppoi_ivcxxdnrsc.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\ooefwznlrtefzlymlvv1ubjtnkitppoi_ivcxxdnrsc.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\ooefwznlrtefzlymlvv1ubjtnkitppoi_ivcxxdnrsc.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\pru33qjshpzsmg3z6vywnrjtnkitppoi_ivcxxdnrsc.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\pru33qjshpzsmg3z6vywnrjtnkitppoi_ivcxxdnrsc.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\robotobold.woff">
+ <Link>Resources\dashboard-ui\fonts\roboto\robotobold.woff</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\robotolight.woff">
+ <Link>Resources\dashboard-ui\fonts\roboto\robotolight.woff</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\robotomedium.woff">
+ <Link>Resources\dashboard-ui\fonts\roboto\robotomedium.woff</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\robotoregular.woff">
+ <Link>Resources\dashboard-ui\fonts\roboto\robotoregular.woff</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\robotothin.woff">
+ <Link>Resources\dashboard-ui\fonts\roboto\robotothin.woff</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\rxzjdnzeo3r5zsexge8uuvtxra8tvwticgirnjhmvjw.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\rxzjdnzeo3r5zsexge8uuvtxra8tvwticgirnjhmvjw.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\style.css">
+ <Link>Resources\dashboard-ui\fonts\roboto\style.css</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\ty9dfvlaziwdqq2dhoyjphtbgvql8ndjpwnre27mub0.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\ty9dfvlaziwdqq2dhoyjphtbgvql8ndjpwnre27mub0.woff2</Link>
+ </BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\fonts\roboto\vvxugkzxbhtx_s_vctlpghtbgvql8ndjpwnre27mub0.woff2">
+ <Link>Resources\dashboard-ui\fonts\roboto\vvxugkzxbhtx_s_vctlpghtbgvql8ndjpwnre27mub0.woff2</Link>
+ </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\legacy\buttonenabled.js">
<Link>Resources\dashboard-ui\legacy\buttonenabled.js</Link>
</BundleResource>
@@ -2231,36 +2228,15 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\encodingsettings.js">
<Link>Resources\dashboard-ui\scripts\encodingsettings.js</Link>
</BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\episodes.js">
- <Link>Resources\dashboard-ui\scripts\episodes.js</Link>
- </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\forgotpassword.js">
<Link>Resources\dashboard-ui\scripts\forgotpassword.js</Link>
</BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\forgotpasswordpin.js">
<Link>Resources\dashboard-ui\scripts\forgotpasswordpin.js</Link>
</BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\gamegenrepage.js">
- <Link>Resources\dashboard-ui\scripts\gamegenrepage.js</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\gamespage.js">
- <Link>Resources\dashboard-ui\scripts\gamespage.js</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\gamesrecommendedpage.js">
- <Link>Resources\dashboard-ui\scripts\gamesrecommendedpage.js</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\gamestudiospage.js">
- <Link>Resources\dashboard-ui\scripts\gamestudiospage.js</Link>
- </BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\gamesystemspage.js">
- <Link>Resources\dashboard-ui\scripts\gamesystemspage.js</Link>
- </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\homefavorites.js">
<Link>Resources\dashboard-ui\scripts\homefavorites.js</Link>
</BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\homeupcoming.js">
- <Link>Resources\dashboard-ui\scripts\homeupcoming.js</Link>
- </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\indexpage.js">
<Link>Resources\dashboard-ui\scripts\indexpage.js</Link>
</BundleResource>
@@ -2345,9 +2321,6 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\moviesrecommended.js">
<Link>Resources\dashboard-ui\scripts\moviesrecommended.js</Link>
</BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\moviestudios.js">
- <Link>Resources\dashboard-ui\scripts\moviestudios.js</Link>
- </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\movietrailers.js">
<Link>Resources\dashboard-ui\scripts\movietrailers.js</Link>
</BundleResource>
@@ -2357,12 +2330,12 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\musicartists.js">
<Link>Resources\dashboard-ui\scripts\musicartists.js</Link>
</BundleResource>
- <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\musicfolders.js">
- <Link>Resources\dashboard-ui\scripts\musicfolders.js</Link>
- </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\musicgenres.js">
<Link>Resources\dashboard-ui\scripts\musicgenres.js</Link>
</BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\musicplaylists.js">
+ <Link>Resources\dashboard-ui\scripts\musicplaylists.js</Link>
+ </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\musicrecommended.js">
<Link>Resources\dashboard-ui\scripts\musicrecommended.js</Link>
</BundleResource>
@@ -2435,6 +2408,9 @@
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\searchpage.js">
<Link>Resources\dashboard-ui\scripts\searchpage.js</Link>
</BundleResource>
+ <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\searchtab.js">
+ <Link>Resources\dashboard-ui\scripts\searchtab.js</Link>
+ </BundleResource>
<BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\scripts\secondaryitems.js">
<Link>Resources\dashboard-ui\scripts\secondaryitems.js</Link>
</BundleResource>
diff --git a/MediaBrowser.Server.Mac/ImageMagickSharp.dll.config b/MediaBrowser.Server.Mac/ImageMagickSharp.dll.config
deleted file mode 100644
index 0ad6d1e60..000000000
--- a/MediaBrowser.Server.Mac/ImageMagickSharp.dll.config
+++ /dev/null
@@ -1,3 +0,0 @@
-<configuration>
- <dllmap dll="CORE_RL_Wand_.dll" target="libMagickWand-6.Q8.dylib" os="osx"/>
-</configuration> \ No newline at end of file
diff --git a/MediaBrowser.Server.Mac/MacAppHost.cs b/MediaBrowser.Server.Mac/MacAppHost.cs
index 304472529..4b29ba3a7 100644
--- a/MediaBrowser.Server.Mac/MacAppHost.cs
+++ b/MediaBrowser.Server.Mac/MacAppHost.cs
@@ -18,7 +18,7 @@ namespace MediaBrowser.Server.Mac
{
public class MacAppHost : ApplicationHost
{
- public MacAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action<string, string> certificateGenerator, Func<string> defaultUsernameFactory) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory)
+ public MacAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action<string, string, string> certificateGenerator, Func<string> defaultUsernameFactory) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory)
{
}
diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs
index d703f7d0d..932ff6105 100644
--- a/MediaBrowser.Server.Mac/Main.cs
+++ b/MediaBrowser.Server.Mac/Main.cs
@@ -32,6 +32,7 @@ using Mono.Unix.Native;
using MediaBrowser.Model.System;
using MediaBrowser.Model.IO;
using Emby.Server.Core.Logging;
+using Emby.Drawing.Net;
namespace MediaBrowser.Server.Mac
{
@@ -111,12 +112,7 @@ namespace MediaBrowser.Server.Mac
_fileSystem = fileSystem;
- var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger,
- logManager,
- fileSystem,
- options,
- () => AppHost.HttpClient,
- appPaths);
+ var imageEncoder = new GDIImageEncoder(fileSystem, logManager.GetLogger("GDI"));
AppHost = new MacAppHost(appPaths,
logManager,
@@ -142,9 +138,9 @@ namespace MediaBrowser.Server.Mac
Task.Run (() => StartServer(CancellationToken.None));
}
- private static void GenerateCertificate(string certPath, string certHost)
+ private static void GenerateCertificate(string certPath, string certHost, string certPassword)
{
- CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger);
+ CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, certPassword, _logger);
}
private static EnvironmentInfo GetEnvironmentInfo()
diff --git a/MediaBrowser.Server.Startup.Common/ImageEncoderHelper.cs b/MediaBrowser.Server.Mono/ImageEncoderHelper.cs
index ddbde2f66..ddbde2f66 100644
--- a/MediaBrowser.Server.Startup.Common/ImageEncoderHelper.cs
+++ b/MediaBrowser.Server.Mono/ImageEncoderHelper.cs
diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
index 17d9767f6..bcdfa858f 100644
--- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
+++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
@@ -117,6 +117,7 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
+ <Compile Include="ImageEncoderHelper.cs" />
<Compile Include="MonoAppHost.cs" />
<Compile Include="Native\MonoFileSystem.cs" />
<Compile Include="Native\PowerManagement.cs" />
diff --git a/MediaBrowser.Server.Mono/MonoAppHost.cs b/MediaBrowser.Server.Mono/MonoAppHost.cs
index 54fd45019..09c409a2c 100644
--- a/MediaBrowser.Server.Mono/MonoAppHost.cs
+++ b/MediaBrowser.Server.Mono/MonoAppHost.cs
@@ -19,7 +19,7 @@ namespace MediaBrowser.Server.Mono
{
public class MonoAppHost : ApplicationHost
{
- public MonoAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action<string, string> certificateGenerator, Func<string> defaultUsernameFactory) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory)
+ public MonoAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action<string, string, string> certificateGenerator, Func<string> defaultUsernameFactory) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory)
{
}
diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs
index 66851f7e9..b79c8c1f7 100644
--- a/MediaBrowser.Server.Mono/Program.cs
+++ b/MediaBrowser.Server.Mono/Program.cs
@@ -159,9 +159,9 @@ namespace MediaBrowser.Server.Mono
Task.WaitAll(task);
}
- private static void GenerateCertificate(string certPath, string certHost)
+ private static void GenerateCertificate(string certPath, string certHost, string certPassword)
{
- CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger);
+ CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, certPassword, _logger);
}
private static MonoEnvironmentInfo GetEnvironmentInfo()
@@ -258,7 +258,12 @@ namespace MediaBrowser.Server.Mono
if (!Debugger.IsAttached)
{
- Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(exception));
+ var message = LogHelper.GetLogMessage(exception).ToString();
+
+ if (message.IndexOf("InotifyWatcher", StringComparison.OrdinalIgnoreCase) == -1)
+ {
+ Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(exception));
+ }
}
}
diff --git a/MediaBrowser.Server.Mono/app.config b/MediaBrowser.Server.Mono/app.config
index 07c113f3e..8f21d4a67 100644
--- a/MediaBrowser.Server.Mono/app.config
+++ b/MediaBrowser.Server.Mono/app.config
@@ -11,6 +11,8 @@
<add key="ReleaseProgramDataPath" value="ProgramData-Server" />
</appSettings>
<runtime>
+ <legacyUnhandledExceptionPolicy enabled="1" />
+
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
diff --git a/MediaBrowser.Server.Startup.Common/Cryptography/CertificateGenerator.cs b/MediaBrowser.Server.Startup.Common/Cryptography/CertificateGenerator.cs
index 9e14b7713..4f5b3d004 100644
--- a/MediaBrowser.Server.Startup.Common/Cryptography/CertificateGenerator.cs
+++ b/MediaBrowser.Server.Startup.Common/Cryptography/CertificateGenerator.cs
@@ -12,6 +12,7 @@ namespace Emby.Common.Implementations.Security
public static void CreateSelfSignCertificatePfx(
string fileName,
string hostname,
+ string password,
ILogger logger)
{
if (string.IsNullOrWhiteSpace(fileName))
@@ -43,7 +44,7 @@ namespace Emby.Common.Implementations.Security
cb.NotAfter = notAfter;
cb.SubjectName = subject;
cb.SubjectPublicKey = subjectKey;
-
+
// signature
cb.Hash = "SHA256";
byte[] rawcert = cb.Sign(issuerKey);
@@ -59,6 +60,7 @@ namespace Emby.Common.Implementations.Security
attributes.Add(PKCS9.localKeyId, list);
p12.AddCertificate(new X509Certificate(rawcert), attributes);
+ p12.Password = password;
p12.AddPkcs8ShroudedKeyBag(subjectKey, attributes);
p12.SaveToFile(fileName);
diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
index 5eb492166..5955d4c96 100644
--- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
+++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
@@ -37,8 +37,8 @@
<Reference Include="Emby.Server.Core">
<HintPath>..\ThirdParty\emby\Emby.Server.Core.dll</HintPath>
</Reference>
- <Reference Include="Microsoft.IO.RecyclableMemoryStream, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
- <HintPath>..\packages\Microsoft.IO.RecyclableMemoryStream.1.2.1\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll</HintPath>
+ <Reference Include="Microsoft.IO.RecyclableMemoryStream, Version=1.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>..\packages\Microsoft.IO.RecyclableMemoryStream.1.2.2\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
@@ -73,25 +73,12 @@
<Compile Include="Cryptography\X509Extension.cs" />
<Compile Include="Cryptography\X509Extensions.cs" />
<Compile Include="Cryptography\X520Attributes.cs" />
- <Compile Include="ImageEncoderHelper.cs" />
<Compile Include="IO\MemoryStreamProvider.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SystemEvents.cs" />
<Compile Include="UpdateLevelHelper.cs" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\Emby.Drawing.ImageMagick\Emby.Drawing.ImageMagick.csproj">
- <Project>{6cfee013-6e7c-432b-ac37-cabf0880c69a}</Project>
- <Name>Emby.Drawing.ImageMagick</Name>
- </ProjectReference>
- <ProjectReference Include="..\Emby.Drawing.Net\Emby.Drawing.Net.csproj">
- <Project>{c97a239e-a96c-4d64-a844-ccf8cc30aecb}</Project>
- <Name>Emby.Drawing.Net</Name>
- </ProjectReference>
- <ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj">
- <Project>{08fff49b-f175-4807-a2b5-73b0ebd9f716}</Project>
- <Name>Emby.Drawing</Name>
- </ProjectReference>
<ProjectReference Include="..\Emby.Server.Implementations\Emby.Server.Implementations.csproj">
<Project>{e383961b-9356-4d5d-8233-9a1079d03055}</Project>
<Name>Emby.Server.Implementations</Name>
diff --git a/MediaBrowser.Server.Startup.Common/packages.config b/MediaBrowser.Server.Startup.Common/packages.config
index d329f2cce..4b6266585 100644
--- a/MediaBrowser.Server.Startup.Common/packages.config
+++ b/MediaBrowser.Server.Startup.Common/packages.config
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Microsoft.IO.RecyclableMemoryStream" version="1.2.1" targetFramework="net46" />
+ <package id="Microsoft.IO.RecyclableMemoryStream" version="1.2.2" targetFramework="net46" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.ServerApplication/ImageEncoderHelper.cs b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs
new file mode 100644
index 000000000..ddbde2f66
--- /dev/null
+++ b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs
@@ -0,0 +1,48 @@
+using System;
+using Emby.Drawing;
+using Emby.Drawing.Net;
+using Emby.Drawing.ImageMagick;
+using Emby.Server.Core;
+using Emby.Server.Implementations;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+
+namespace MediaBrowser.Server.Startup.Common
+{
+ public class ImageEncoderHelper
+ {
+ public static IImageEncoder GetImageEncoder(ILogger logger,
+ ILogManager logManager,
+ IFileSystem fileSystem,
+ StartupOptions startupOptions,
+ Func<IHttpClient> httpClient,
+ IApplicationPaths appPaths)
+ {
+ if (!startupOptions.ContainsOption("-enablegdi"))
+ {
+ try
+ {
+ return new ImageMagickEncoder(logManager.GetLogger("ImageMagick"), appPaths, httpClient, fileSystem);
+ }
+ catch
+ {
+ logger.Error("Error loading ImageMagick. Will revert to GDI.");
+ }
+ }
+
+ try
+ {
+ return new GDIImageEncoder(fileSystem, logManager.GetLogger("GDI"));
+ }
+ catch
+ {
+ logger.Error("Error loading GDI. Will revert to NullImageEncoder.");
+ }
+
+ return new NullImageEncoder();
+ }
+ }
+}
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index 3643aab48..8e38c9a98 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -391,9 +391,9 @@ namespace MediaBrowser.ServerApplication
}
}
- private static void GenerateCertificate(string certPath, string certHost)
+ private static void GenerateCertificate(string certPath, string certHost, string certPassword)
{
- CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger);
+ CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, certPassword, _logger);
}
private static ServerNotifyIcon _serverNotifyIcon;
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index b968c2fb6..749468fe2 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -135,6 +135,7 @@
<Compile Include="BackgroundServiceInstaller.cs">
<SubType>Component</SubType>
</Compile>
+ <Compile Include="ImageEncoderHelper.cs" />
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
diff --git a/MediaBrowser.ServerApplication/Native/LoopUtil.cs b/MediaBrowser.ServerApplication/Native/LoopUtil.cs
index 6160f853f..9a96f5518 100644
--- a/MediaBrowser.ServerApplication/Native/LoopUtil.cs
+++ b/MediaBrowser.ServerApplication/Native/LoopUtil.cs
@@ -145,16 +145,6 @@ namespace MediaBrowser.ServerApplication.Native
{
AppContainer app = new AppContainer(PI_app.appContainerName, PI_app.displayName, PI_app.workingDirectory, PI_app.appContainerSid);
- var app_capabilities = LoopUtil.getCapabilites(PI_app.capabilities);
- if (app_capabilities.Count > 0)
- {
- //var sid = new SecurityIdentifier(app_capabilities[0], 0);
-
- IntPtr arrayValue = IntPtr.Zero;
- //var b = LoopUtil.ConvertStringSidToSid(app_capabilities[0].Sid, out arrayValue);
- //string mysid;
- //var b = LoopUtil.ConvertSidToStringSid(app_capabilities[0].Sid, out mysid);
- }
app.LoopUtil = CheckLoopback(PI_app.appContainerSid);
Apps.Add(app);
}
@@ -209,42 +199,6 @@ namespace MediaBrowser.ServerApplication.Native
util.SaveLoopbackState();
}
- private static List<SID_AND_ATTRIBUTES> getCapabilites(INET_FIREWALL_AC_CAPABILITIES cap)
- {
- List<SID_AND_ATTRIBUTES> mycap = new List<SID_AND_ATTRIBUTES>();
-
- IntPtr arrayValue = cap.capabilities;
-
- var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
- for (var i = 0; i < cap.count; i++)
- {
- var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES));
- mycap.Add(cur);
- arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize));
- }
-
- return mycap;
-
- }
-
- private static List<SID_AND_ATTRIBUTES> getContainerSID(INET_FIREWALL_AC_CAPABILITIES cap)
- {
- List<SID_AND_ATTRIBUTES> mycap = new List<SID_AND_ATTRIBUTES>();
-
- IntPtr arrayValue = cap.capabilities;
-
- var structSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
- for (var i = 0; i < cap.count; i++)
- {
- var cur = (SID_AND_ATTRIBUTES)Marshal.PtrToStructure(arrayValue, typeof(SID_AND_ATTRIBUTES));
- mycap.Add(cur);
- arrayValue = new IntPtr((long)(arrayValue) + (long)(structSize));
- }
-
- return mycap;
-
- }
-
private static List<SID_AND_ATTRIBUTES> PI_NetworkIsolationGetAppContainerConfig()
{
diff --git a/MediaBrowser.ServerApplication/WindowsAppHost.cs b/MediaBrowser.ServerApplication/WindowsAppHost.cs
index cd293fddf..537c8b323 100644
--- a/MediaBrowser.ServerApplication/WindowsAppHost.cs
+++ b/MediaBrowser.ServerApplication/WindowsAppHost.cs
@@ -25,7 +25,7 @@ namespace MediaBrowser.ServerApplication
{
public class WindowsAppHost : ApplicationHost
{
- public WindowsAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action<string, string> certificateGenerator, Func<string> defaultUsernameFactory)
+ public WindowsAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action<string, string, string> certificateGenerator, Func<string> defaultUsernameFactory)
: base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory)
{
}
diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
index 8880441e2..72389044b 100644
--- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs
+++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
@@ -98,8 +98,8 @@ namespace MediaBrowser.WebDashboard.Api
}
path = GetDashboardResourcePath(path);
- var parent = Path.GetDirectoryName(path);
-
+ var parent = _fileSystem.GetDirectoryName(path);
+
return string.Equals(_basePath, parent, StringComparison.OrdinalIgnoreCase) ||
string.Equals(Path.Combine(_basePath, "voice"), parent, StringComparison.OrdinalIgnoreCase);
}
diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
index a12976f82..dfd4694c3 100644
--- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
+++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
@@ -358,18 +358,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers
break;
}
- case "criticratingsummary":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- item.CriticRatingSummary = val;
- }
-
- break;
- }
-
case "language":
{
var val = reader.ReadElementContentAsString();
@@ -464,17 +452,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers
break;
}
- case "mpaadescription":
- {
- var rating = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(rating))
- {
- item.OfficialRatingDescription = rating;
- }
- break;
- }
-
case "customrating":
{
var val = reader.ReadElementContentAsString();
diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
index 02929f83d..623b109f7 100644
--- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
@@ -19,7 +19,6 @@ using System.Text;
using System.Threading;
using System.Xml;
using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.IO;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Xml;
@@ -42,7 +41,6 @@ namespace MediaBrowser.XbmcMetadata.Savers
"year",
"sorttitle",
"mpaa",
- "mpaadescription",
"aspectratio",
"website",
"collectionnumber",
@@ -56,7 +54,6 @@ namespace MediaBrowser.XbmcMetadata.Savers
"tag",
"runtime",
"actor",
- "criticratingsummary",
"criticrating",
"fileinfo",
"director",
@@ -212,7 +209,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
private void SaveToFile(Stream stream, string path)
{
- FileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path));
var file = FileSystem.GetFileInfo(path);
@@ -557,11 +554,6 @@ namespace MediaBrowser.XbmcMetadata.Savers
writer.WriteElementString("mpaa", item.OfficialRating);
}
- if (!string.IsNullOrEmpty(item.OfficialRatingDescription))
- {
- writer.WriteElementString("mpaadescription", item.OfficialRatingDescription);
- }
-
var hasAspectRatio = item as IHasAspectRatio;
if (hasAspectRatio != null)
{
@@ -662,11 +654,6 @@ namespace MediaBrowser.XbmcMetadata.Savers
writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(UsCulture));
}
- if (!string.IsNullOrEmpty(item.CriticRatingSummary))
- {
- writer.WriteElementString("criticratingsummary", item.CriticRatingSummary);
- }
-
var hasDisplayOrder = item as IHasDisplayOrder;
if (hasDisplayOrder != null)
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index 20681b317..c86e9a71c 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
- <version>3.0.698</version>
+ <version>3.0.699</version>
<title>Emby.Common</title>
<authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 7b5f348c8..f68cf4e41 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
- <version>3.0.698</version>
+ <version>3.0.699</version>
<title>Emby.Server.Core</title>
<authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Emby Server.</description>
<copyright>Copyright © Emby 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.696" />
+ <dependency id="MediaBrowser.Common" version="3.0.699" />
</dependencies>
</metadata>
<files>
diff --git a/SocketHttpListener.Portable/Net/HttpConnection.cs b/SocketHttpListener.Portable/Net/HttpConnection.cs
index 5fe47fc63..ac8ada486 100644
--- a/SocketHttpListener.Portable/Net/HttpConnection.cs
+++ b/SocketHttpListener.Portable/Net/HttpConnection.cs
@@ -217,7 +217,7 @@ namespace SocketHttpListener.Net
{
var supportsDirectSocketAccess = !context.Response.SendChunked && !isExpect100Continue && !secure;
- o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding, _fileSystem, sock, supportsDirectSocketAccess);
+ o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding, _fileSystem, sock, supportsDirectSocketAccess, _logger);
}
else
{
diff --git a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs
index d9f91c0cc..3cb6a0d75 100644
--- a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs
+++ b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs
@@ -480,6 +480,8 @@ namespace SocketHttpListener.Net
headers.SetInternal("Set-Cookie", cookie.ToString());
}
+ headers.SetInternal("Status", status_code.ToString(CultureInfo.InvariantCulture));
+
using (StreamWriter writer = new StreamWriter(ms, encoding, 256, true))
{
writer.Write("HTTP/{0} {1} {2}\r\n", version, status_code, status_description);
diff --git a/SocketHttpListener.Portable/Net/ResponseStream.cs b/SocketHttpListener.Portable/Net/ResponseStream.cs
index 3c79f47c2..dea4049d5 100644
--- a/SocketHttpListener.Portable/Net/ResponseStream.cs
+++ b/SocketHttpListener.Portable/Net/ResponseStream.cs
@@ -5,6 +5,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives;
@@ -26,8 +27,9 @@ namespace SocketHttpListener.Net
private readonly IFileSystem _fileSystem;
private readonly IAcceptSocket _socket;
private readonly bool _supportsDirectSocketAccess;
+ private readonly ILogger _logger;
- internal ResponseStream(Stream stream, HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IAcceptSocket socket, bool supportsDirectSocketAccess)
+ internal ResponseStream(Stream stream, HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IAcceptSocket socket, bool supportsDirectSocketAccess, ILogger logger)
{
this.response = response;
_memoryStreamFactory = memoryStreamFactory;
@@ -35,6 +37,7 @@ namespace SocketHttpListener.Net
_fileSystem = fileSystem;
_socket = socket;
_supportsDirectSocketAccess = supportsDirectSocketAccess;
+ _logger = logger;
this.stream = stream;
}
@@ -309,40 +312,38 @@ namespace SocketHttpListener.Net
public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
{
- //if (_supportsDirectSocketAccess && offset == 0 && count == 0 && !response.SendChunked)
+ //if (_supportsDirectSocketAccess && offset == 0 && count == 0 && !response.SendChunked && response.ContentLength64 > 8192)
//{
- // return TransmitFileOverSocket(path, offset, count, cancellationToken);
+ // return TransmitFileOverSocket(path, offset, count, fileShareMode, cancellationToken);
//}
return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken);
}
private readonly byte[] _emptyBuffer = new byte[] { };
- private async Task TransmitFileOverSocket(string path, long offset, long count, CancellationToken cancellationToken)
+ private Task TransmitFileOverSocket(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
{
MemoryStream ms = GetHeaders(response, _memoryStreamFactory, false);
- var buffer = new byte[] {};
+ byte[] buffer;
if (ms != null)
{
- ms.Position = 0;
-
- byte[] msBuffer;
- _memoryStreamFactory.TryGetBuffer(ms, out msBuffer);
- buffer = msBuffer;
+ using (var msCopy = new MemoryStream())
+ {
+ ms.CopyTo(msCopy);
+ buffer = msCopy.ToArray();
+ }
+ }
+ else
+ {
+ return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken);
}
- await _socket.SendFile(path, buffer, _emptyBuffer, cancellationToken).ConfigureAwait(false);
+ _logger.Info("Socket sending file {0} {1}", path, response.ContentLength64);
+ return _socket.SendFile(path, buffer, _emptyBuffer, cancellationToken);
}
private async Task TransmitFileManaged(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
{
- var chunked = response.SendChunked;
-
- if (!chunked)
- {
- await WriteAsync(_emptyBuffer, 0, 0, cancellationToken).ConfigureAwait(false);
- }
-
using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, fileShareMode, true))
{
if (offset > 0)
@@ -350,7 +351,7 @@ namespace SocketHttpListener.Net
fs.Position = offset;
}
- var targetStream = chunked ? this : stream;
+ var targetStream = this;
if (count > 0)
{
@@ -366,14 +367,23 @@ namespace SocketHttpListener.Net
private static async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength, CancellationToken cancellationToken)
{
var array = new byte[81920];
- int count;
- while ((count = await source.ReadAsync(array, 0, array.Length, cancellationToken).ConfigureAwait(false)) != 0)
+ int bytesRead;
+
+ while ((bytesRead = await source.ReadAsync(array, 0, array.Length, cancellationToken).ConfigureAwait(false)) != 0)
{
- var bytesToCopy = Math.Min(count, copyLength);
+ if (bytesRead == 0)
+ {
+ break;
+ }
+
+ var bytesToWrite = Math.Min(bytesRead, copyLength);
- await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy), cancellationToken).ConfigureAwait(false);
+ if (bytesToWrite > 0)
+ {
+ await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToWrite), cancellationToken).ConfigureAwait(false);
+ }
- copyLength -= bytesToCopy;
+ copyLength -= bytesToWrite;
if (copyLength <= 0)
{