aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Drawing/Common/ImageHeader.cs2
-rw-r--r--Emby.Drawing/Emby.Drawing.csproj8
-rw-r--r--Emby.Drawing/GDI/GDIImageEncoder.cs4
-rw-r--r--Emby.Drawing/ImageMagick/ImageMagickEncoder.cs19
-rw-r--r--Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs27
-rw-r--r--Emby.Drawing/ImageMagick/StripCollageBuilder.cs7
-rw-r--r--Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs7
-rw-r--r--Emby.Drawing/ImageProcessor.cs53
-rw-r--r--MediaBrowser.Api/AppThemeService.cs100
-rw-r--r--MediaBrowser.Api/Devices/DeviceService.cs37
-rw-r--r--MediaBrowser.Api/Dlna/DlnaServerService.cs1
-rw-r--r--MediaBrowser.Api/EnvironmentService.cs20
-rw-r--r--MediaBrowser.Api/Images/ImageByNameService.cs21
-rw-r--r--MediaBrowser.Api/Images/RemoteImageService.cs6
-rw-r--r--MediaBrowser.Api/ItemLookupService.cs8
-rw-r--r--MediaBrowser.Api/ItemRefreshService.cs7
-rw-r--r--MediaBrowser.Api/Library/LibraryHelpers.cs6
-rw-r--r--MediaBrowser.Api/Library/LibraryService.cs7
-rw-r--r--MediaBrowser.Api/Library/LibraryStructureService.cs19
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj15
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs57
-rw-r--r--MediaBrowser.Api/Playback/Dash/MpegDashService.cs13
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs29
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs59
-rw-r--r--MediaBrowser.Api/Playback/MediaInfoService.cs16
-rw-r--r--MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs4
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs1
-rw-r--r--MediaBrowser.Api/Playback/StreamState.cs2
-rw-r--r--MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs2
-rw-r--r--MediaBrowser.Api/StartupWizardService.cs2
-rw-r--r--MediaBrowser.Api/Subtitles/SubtitleService.cs7
-rw-r--r--MediaBrowser.Api/System/SystemService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/UserViewsService.cs34
-rw-r--r--MediaBrowser.Api/packages.config2
-rw-r--r--MediaBrowser.Common.Implementations/Archiving/ZipClient.cs18
-rw-r--r--MediaBrowser.Common.Implementations/BaseApplicationHost.cs15
-rw-r--r--MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs7
-rw-r--r--MediaBrowser.Common.Implementations/Devices/DeviceId.cs17
-rw-r--r--MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs46
-rw-r--r--MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs114
-rw-r--r--MediaBrowser.Common.Implementations/Logging/NlogManager.cs4
-rw-r--r--MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj9
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs9
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs29
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs6
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs2
-rw-r--r--MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs8
-rw-r--r--MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs10
-rw-r--r--MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs10
-rw-r--r--MediaBrowser.Common.Implementations/Updates/InstallationManager.cs8
-rw-r--r--MediaBrowser.Common.Implementations/packages.config4
-rw-r--r--MediaBrowser.Common/IO/IFileSystem.cs53
-rw-r--r--MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs2
-rw-r--r--MediaBrowser.Controller/Channels/IChannelFactory.cs14
-rw-r--r--MediaBrowser.Controller/Channels/IChannelManager.cs2
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs56
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs27
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs4
-rw-r--r--MediaBrowser.Controller/Entities/User.cs10
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs22
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs73
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs4
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvProgram.cs4
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs4
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj17
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs7
-rw-r--r--MediaBrowser.Controller/Net/IHttpServer.cs5
-rw-r--r--MediaBrowser.Controller/Persistence/IItemRepository.cs7
-rw-r--r--MediaBrowser.Controller/Providers/DirectoryService.cs12
-rw-r--r--MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs5
-rw-r--r--MediaBrowser.Controller/Providers/MetadataStatus.cs8
-rw-r--r--MediaBrowser.Controller/Themes/IAppThemeManager.cs38
-rw-r--r--MediaBrowser.Controller/Themes/InternalThemeImage.cs31
-rw-r--r--MediaBrowser.Controller/packages.config2
-rw-r--r--MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs642
-rw-r--r--MediaBrowser.Dlna/DlnaManager.cs10
-rw-r--r--MediaBrowser.Dlna/Main/DlnaEntryPoint.cs2
-rw-r--r--MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs7
-rw-r--r--MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs8
-rw-r--r--MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs7
-rw-r--r--MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs7
-rw-r--r--MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs7
-rw-r--r--MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs7
-rw-r--r--MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs7
-rw-r--r--MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs7
-rw-r--r--MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs7
-rw-r--r--MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs7
-rw-r--r--MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs17
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs6
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs52
-rw-r--r--MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs25
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs20
-rw-r--r--MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj9
-rw-r--r--MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj9
-rw-r--r--MediaBrowser.Model/Configuration/EncodingOptions.cs3
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs22
-rw-r--r--MediaBrowser.Model/Dlna/ConditionProcessor.cs1
-rw-r--r--MediaBrowser.Model/Dlna/StreamBuilder.cs23
-rw-r--r--MediaBrowser.Model/Dto/BaseItemDto.cs2
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj15
-rw-r--r--MediaBrowser.Model/Net/MimeTypes.cs2
-rw-r--r--MediaBrowser.Model/Themes/AppTheme.cs22
-rw-r--r--MediaBrowser.Model/Themes/AppThemeInfo.cs9
-rw-r--r--MediaBrowser.Model/Themes/ThemeImage.cs18
-rw-r--r--MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs2
-rw-r--r--MediaBrowser.Providers/Folders/DefaultImageProvider.cs14
-rw-r--r--MediaBrowser.Providers/ImagesByName/ImageUtils.cs4
-rw-r--r--MediaBrowser.Providers/Manager/ImageSaver.cs2
-rw-r--r--MediaBrowser.Providers/Manager/ItemImageProvider.cs4
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs20
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs22
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj4
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs6
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs2
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs2
-rw-r--r--MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs6
-rw-r--r--MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs7
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbProvider.cs4
-rw-r--r--MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs6
-rw-r--r--MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs2
-rw-r--r--MediaBrowser.Providers/Music/AudioDbArtistProvider.cs2
-rw-r--r--MediaBrowser.Providers/Music/FanArtArtistProvider.cs2
-rw-r--r--MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs6
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbImageProvider.cs3
-rw-r--r--MediaBrowser.Providers/People/MovieDbPersonProvider.cs2
-rw-r--r--MediaBrowser.Providers/Photos/PhotoProvider.cs159
-rw-r--r--MediaBrowser.Providers/Subtitles/SubtitleManager.cs2
-rw-r--r--MediaBrowser.Providers/TV/DummySeasonProvider.cs9
-rw-r--r--MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs6
-rw-r--r--MediaBrowser.Providers/TV/FanartSeriesProvider.cs2
-rw-r--r--MediaBrowser.Providers/TV/MissingEpisodeProvider.cs11
-rw-r--r--MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs2
-rw-r--r--MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs4
-rw-r--r--MediaBrowser.Providers/TV/SeriesMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/TV/SeriesPostScanTask.cs7
-rw-r--r--MediaBrowser.Providers/TV/TvdbPrescanTask.cs8
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeriesProvider.cs15
-rw-r--r--MediaBrowser.Providers/packages.config2
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs33
-rw-r--r--MediaBrowser.Server.Implementations/Collections/CollectionManager.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs7
-rw-r--r--MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs10
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs11
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectManager.cs13
-rw-r--r--MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs7
-rw-r--r--MediaBrowser.Server.Implementations/Devices/DeviceManager.cs6
-rw-r--r--MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Dto/DtoService.cs6
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs4
-rw-r--r--MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs12
-rw-r--r--MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs12
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs9
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs41
-rw-r--r--MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/LibraryManager.cs53
-rw-r--r--MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs14
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs26
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserManager.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserViewManager.cs64
-rw-r--r--MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs7
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs171
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs7
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs5
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs5
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs25
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs23
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs57
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs16
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs13
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/ar.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/bg-BG.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/ca.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/core.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/cs.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/da.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/de.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/el.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/en-GB.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/en-US.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/es-AR.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/es-MX.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/es.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/fi.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/fr.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/gsw.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/he.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/hr.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/it.json55
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/kk.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/ko.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/ms.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/nb.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/nl.json5
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/pl.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/pt-BR.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/pt-PT.json5
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/ro.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/ru.json23
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/sl-SI.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/sv.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/tr.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/uk.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/vi.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/zh-CN.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/zh-HK.json177
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs4
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj38
-rw-r--r--MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs77
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs160
-rw-r--r--MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs7
-rw-r--r--MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs10
-rw-r--r--MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs11
-rw-r--r--MediaBrowser.Server.Implementations/Sync/MediaSync.cs9
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncManager.cs37
-rw-r--r--MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs168
-rw-r--r--MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs13
-rw-r--r--MediaBrowser.Server.Implementations/packages.config2
-rw-r--r--MediaBrowser.Server.Mac.userprefs21
-rw-r--r--MediaBrowser.Server.Startup.Common/ApplicationHost.cs35
-rw-r--r--MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs21
-rw-r--r--MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs20
-rw-r--r--MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs16
-rw-r--r--MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs91
-rw-r--r--MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs3
-rw-r--r--MediaBrowser.Server.Startup.Common/UnhandledExceptionWriter.cs4
-rw-r--r--MediaBrowser.ServerApplication/ServerNotifyIcon.cs41
-rw-r--r--MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/unit.srt2
-rw-r--r--MediaBrowser.WebDashboard/Api/DashboardService.cs34
-rw-r--r--MediaBrowser.WebDashboard/Api/PackageCreator.cs1
-rw-r--r--MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj149
-rw-r--r--MediaBrowser.WebDashboard/packages.config2
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs2
-rw-r--r--Nuget/MediaBrowser.Common.Internal.nuspec6
-rw-r--r--Nuget/MediaBrowser.Common.nuspec2
-rw-r--r--Nuget/MediaBrowser.Model.Signed.nuspec2
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec4
-rw-r--r--OpenSubtitlesHandler/MovieHasher.cs12
-rw-r--r--OpenSubtitlesHandler/Utilities.cs2
-rw-r--r--SharedVersion.cs4
247 files changed, 2624 insertions, 2108 deletions
diff --git a/Emby.Drawing/Common/ImageHeader.cs b/Emby.Drawing/Common/ImageHeader.cs
index b66bd71ea..59df5c04f 100644
--- a/Emby.Drawing/Common/ImageHeader.cs
+++ b/Emby.Drawing/Common/ImageHeader.cs
@@ -220,4 +220,4 @@ namespace Emby.Drawing.Common
throw new ArgumentException(ErrorMessage);
}
}
-}
+} \ No newline at end of file
diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj
index ab53f7550..800756ee9 100644
--- a/Emby.Drawing/Emby.Drawing.csproj
+++ b/Emby.Drawing/Emby.Drawing.csproj
@@ -36,6 +36,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll</HintPath>
</Reference>
+ <Reference Include="policy.2.0.taglib-sharp">
+ <HintPath>..\packages\taglib.2.1.0.0\lib\policy.2.0.taglib-sharp.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
@@ -44,11 +47,15 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
+ <Reference Include="taglib-sharp">
+ <HintPath>..\packages\taglib.2.1.0.0\lib\taglib-sharp.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
+ <Compile Include="Common\ImageHeader.cs" />
<Compile Include="GDI\DynamicImageHelpers.cs" />
<Compile Include="GDI\GDIImageEncoder.cs" />
<Compile Include="GDI\ImageExtensions.cs" />
@@ -56,7 +63,6 @@
<Compile Include="GDI\PlayedIndicatorDrawer.cs" />
<Compile Include="GDI\UnplayedCountIndicator.cs" />
<Compile Include="IImageEncoder.cs" />
- <Compile Include="Common\ImageHeader.cs" />
<Compile Include="ImageHelpers.cs" />
<Compile Include="ImageMagick\ImageMagickEncoder.cs" />
<Compile Include="ImageMagick\StripCollageBuilder.cs" />
diff --git a/Emby.Drawing/GDI/GDIImageEncoder.cs b/Emby.Drawing/GDI/GDIImageEncoder.cs
index 7e3ca530b..1eabce74e 100644
--- a/Emby.Drawing/GDI/GDIImageEncoder.cs
+++ b/Emby.Drawing/GDI/GDIImageEncoder.cs
@@ -66,7 +66,7 @@ namespace Emby.Drawing.GDI
{
using (var croppedImage = image.CropWhitespace())
{
- Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
using (var outputStream = _fileSystem.GetFileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.Read, false))
{
@@ -120,7 +120,7 @@ namespace Emby.Drawing.GDI
var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat);
- Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
// Save to the cache location
using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, false))
diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
index 6ff40d1cf..2f8577acc 100644
--- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
+++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
@@ -8,6 +8,7 @@ using MediaBrowser.Model.Logging;
using System;
using System.IO;
using System.Linq;
+using MediaBrowser.Common.IO;
namespace Emby.Drawing.ImageMagick
{
@@ -15,13 +16,15 @@ namespace Emby.Drawing.ImageMagick
{
private readonly ILogger _logger;
private readonly IApplicationPaths _appPaths;
- private readonly IHttpClient _httpClient;
+ private readonly IHttpClient _httpClient;
+ private readonly IFileSystem _fileSystem;
- public ImageMagickEncoder(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient)
+ public ImageMagickEncoder(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IFileSystem fileSystem)
{
_logger = logger;
_appPaths = appPaths;
_httpClient = httpClient;
+ _fileSystem = fileSystem;
LogImageMagickVersion();
}
@@ -77,7 +80,7 @@ namespace Emby.Drawing.ImageMagick
try
{
var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp");
- Directory.CreateDirectory(Path.GetDirectoryName(tmpPath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath));
using (var wand = new MagickWand(1, 1, new PixelWand("none", 1)))
{
@@ -181,14 +184,14 @@ namespace Emby.Drawing.ImageMagick
{
var currentImageSize = new ImageSize(imageWidth, imageHeight);
- var task = new PlayedIndicatorDrawer(_appPaths, _httpClient).DrawPlayedIndicator(wand, currentImageSize);
+ var task = new PlayedIndicatorDrawer(_appPaths, _httpClient, _fileSystem).DrawPlayedIndicator(wand, currentImageSize);
Task.WaitAll(task);
}
else if (options.UnplayedCount.HasValue)
{
var currentImageSize = new ImageSize(imageWidth, imageHeight);
- new UnplayedCountIndicator(_appPaths).DrawUnplayedCountIndicator(wand, currentImageSize, options.UnplayedCount.Value);
+ new UnplayedCountIndicator(_appPaths, _fileSystem).DrawUnplayedCountIndicator(wand, currentImageSize, options.UnplayedCount.Value);
}
if (options.PercentPlayed > 0)
@@ -209,15 +212,15 @@ namespace Emby.Drawing.ImageMagick
if (ratio >= 1.4)
{
- new StripCollageBuilder(_appPaths).BuildThumbCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
+ new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
}
else if (ratio >= .9)
{
- new StripCollageBuilder(_appPaths).BuildSquareCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
+ new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
}
else
{
- new StripCollageBuilder(_appPaths).BuildPosterCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
+ new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height, options.Text);
}
}
diff --git a/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs b/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs
index 1c751de1f..b5912788f 100644
--- a/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs
+++ b/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Model.Drawing;
using System;
using System.IO;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace Emby.Drawing.ImageMagick
{
@@ -14,12 +15,14 @@ namespace Emby.Drawing.ImageMagick
private const int OffsetFromTopRightCorner = 38;
private readonly IApplicationPaths _appPaths;
- private readonly IHttpClient _iHttpClient;
+ private readonly IHttpClient _iHttpClient;
+ private readonly IFileSystem _fileSystem;
- public PlayedIndicatorDrawer(IApplicationPaths appPaths, IHttpClient iHttpClient)
+ public PlayedIndicatorDrawer(IApplicationPaths appPaths, IHttpClient iHttpClient, IFileSystem fileSystem)
{
_appPaths = appPaths;
_iHttpClient = iHttpClient;
+ _fileSystem = fileSystem;
}
public async Task DrawPlayedIndicator(MagickWand wand, ImageSize imageSize)
@@ -38,7 +41,7 @@ namespace Emby.Drawing.ImageMagick
pixel.Opacity = 0;
pixel.Color = "white";
draw.FillColor = pixel;
- draw.Font = await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf", _appPaths, _iHttpClient).ConfigureAwait(false);
+ draw.Font = await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf", _appPaths, _iHttpClient, _fileSystem).ConfigureAwait(false);
draw.FontSize = FontSize;
draw.FontStyle = FontStyleType.NormalStyle;
draw.TextAlignment = TextAlignType.CenterAlign;
@@ -52,18 +55,18 @@ namespace Emby.Drawing.ImageMagick
}
}
- internal static string ExtractFont(string name, IApplicationPaths paths)
+ internal static string ExtractFont(string name, IApplicationPaths paths, IFileSystem fileSystem)
{
var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name);
- if (File.Exists(filePath))
+ if (fileSystem.FileExists(filePath))
{
return filePath;
}
var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name;
var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf");
- Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
+ fileSystem.CreateDirectory(Path.GetDirectoryName(tempPath));
using (var stream = typeof(PlayedIndicatorDrawer).Assembly.GetManifestResourceStream(namespacePath))
{
@@ -73,11 +76,11 @@ namespace Emby.Drawing.ImageMagick
}
}
- Directory.CreateDirectory(Path.GetDirectoryName(filePath));
+ fileSystem.CreateDirectory(Path.GetDirectoryName(filePath));
try
{
- File.Copy(tempPath, filePath, false);
+ fileSystem.CopyFile(tempPath, filePath, false);
}
catch (IOException)
{
@@ -87,11 +90,11 @@ namespace Emby.Drawing.ImageMagick
return tempPath;
}
- internal static async Task<string> DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient)
+ internal static async Task<string> DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient, IFileSystem fileSystem)
{
var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name);
- if (File.Exists(filePath))
+ if (fileSystem.FileExists(filePath))
{
return filePath;
}
@@ -103,11 +106,11 @@ namespace Emby.Drawing.ImageMagick
}).ConfigureAwait(false);
- Directory.CreateDirectory(Path.GetDirectoryName(filePath));
+ fileSystem.CreateDirectory(Path.GetDirectoryName(filePath));
try
{
- File.Copy(tempPath, filePath, false);
+ fileSystem.CopyFile(tempPath, filePath, false);
}
catch (IOException)
{
diff --git a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs
index 7ed0f36e2..92eb1cd59 100644
--- a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs
+++ b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs
@@ -2,16 +2,19 @@
using MediaBrowser.Common.Configuration;
using System;
using System.Collections.Generic;
+using MediaBrowser.Common.IO;
namespace Emby.Drawing.ImageMagick
{
public class StripCollageBuilder
{
private readonly IApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
- public StripCollageBuilder(IApplicationPaths appPaths)
+ public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem)
{
_appPaths = appPaths;
+ _fileSystem = fileSystem;
}
public void BuildPosterCollage(List<string> paths, string outputPath, int width, int height, string text)
@@ -490,7 +493,7 @@ namespace Emby.Drawing.ImageMagick
private string MontserratLightFont
{
- get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths); }
+ get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths, _fileSystem); }
}
}
}
diff --git a/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs b/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs
index dd25004d6..92601313a 100644
--- a/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs
+++ b/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs
@@ -1,5 +1,6 @@
using ImageMagickSharp;
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
using MediaBrowser.Model.Drawing;
using System.Globalization;
@@ -10,10 +11,12 @@ namespace Emby.Drawing.ImageMagick
private const int OffsetFromTopRightCorner = 38;
private readonly IApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
- public UnplayedCountIndicator(IApplicationPaths appPaths)
+ public UnplayedCountIndicator(IApplicationPaths appPaths, IFileSystem fileSystem)
{
_appPaths = appPaths;
+ _fileSystem = fileSystem;
}
public void DrawUnplayedCountIndicator(MagickWand wand, ImageSize imageSize, int count)
@@ -33,7 +36,7 @@ namespace Emby.Drawing.ImageMagick
pixel.Opacity = 0;
pixel.Color = "white";
draw.FillColor = pixel;
- draw.Font = PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths);
+ draw.Font = PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths, _fileSystem);
draw.FontStyle = FontStyleType.NormalStyle;
draw.TextAlignment = TextAlignType.CenterAlign;
draw.FontWeight = FontWeightType.RegularStyle;
diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs
index 970b463cd..471037801 100644
--- a/Emby.Drawing/ImageProcessor.cs
+++ b/Emby.Drawing/ImageProcessor.cs
@@ -1,5 +1,4 @@
-using Emby.Drawing.Common;
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Drawing;
@@ -17,6 +16,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Emby.Drawing.Common;
namespace Emby.Drawing
{
@@ -215,18 +215,21 @@ namespace Emby.Drawing
{
CheckDisposed();
- if (!File.Exists(cacheFilePath))
+ if (!_fileSystem.FileExists(cacheFilePath))
{
var newWidth = Convert.ToInt32(newSize.Width);
var newHeight = Convert.ToInt32(newSize.Height);
- Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false);
imageProcessingLockTaken = true;
_imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options);
+
+ // ImageMagick doesn't seem to always release it right away
+ await Task.Delay(100).ConfigureAwait(false);
}
}
finally
@@ -267,7 +270,7 @@ namespace Emby.Drawing
await semaphore.WaitAsync().ConfigureAwait(false);
// Check again in case of contention
- if (File.Exists(croppedImagePath))
+ if (_fileSystem.FileExists(croppedImagePath))
{
semaphore.Release();
return GetResult(croppedImagePath);
@@ -277,7 +280,7 @@ namespace Emby.Drawing
try
{
- Directory.CreateDirectory(Path.GetDirectoryName(croppedImagePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(croppedImagePath));
await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false);
imageProcessingLockTaken = true;
@@ -363,7 +366,7 @@ namespace Emby.Drawing
/// <returns>ImageSize.</returns>
public ImageSize GetImageSize(string path)
{
- return GetImageSize(path, File.GetLastWriteTimeUtc(path), false);
+ return GetImageSize(path, _fileSystem.GetLastWriteTimeUtc(path), false);
}
public ImageSize GetImageSize(ItemImageInfo info)
@@ -396,6 +399,8 @@ namespace Emby.Drawing
{
size = GetImageSizeInternal(path, allowSlowMethod);
+ StartSaveImageSizeTimer();
+
_cachedImagedSizes.AddOrUpdate(cacheHash, size, (keyName, oldValue) => size);
}
@@ -410,28 +415,26 @@ namespace Emby.Drawing
/// <returns>ImageSize.</returns>
private ImageSize GetImageSizeInternal(string path, bool allowSlowMethod)
{
- ImageSize size;
-
try
{
- size = ImageHeader.GetDimensions(path, _logger, _fileSystem);
- }
- catch
- {
- if (!allowSlowMethod)
+ using (var file = TagLib.File.Create(path))
{
- throw;
- }
- //_logger.Info("Failed to read image header for {0}. Doing it the slow way.", path);
+ var image = file as TagLib.Image.File;
- CheckDisposed();
+ var properties = image.Properties;
- size = _imageEncoder.GetImageSize(path);
+ return new ImageSize
+ {
+ Height = properties.PhotoHeight,
+ Width = properties.PhotoWidth
+ };
+ }
+ }
+ catch
+ {
}
- StartSaveImageSizeTimer();
-
- return size;
+ return ImageHeader.GetDimensions(path, _logger, _fileSystem);
}
private readonly Timer _saveImageSizeTimer;
@@ -449,7 +452,7 @@ namespace Emby.Drawing
try
{
var path = ImageSizeFile;
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(_cachedImagedSizes, path);
}
catch (Exception ex)
@@ -621,7 +624,7 @@ namespace Emby.Drawing
await semaphore.WaitAsync().ConfigureAwait(false);
// Check again in case of contention
- if (File.Exists(enhancedImagePath))
+ if (_fileSystem.FileExists(enhancedImagePath))
{
semaphore.Release();
return enhancedImagePath;
@@ -631,7 +634,7 @@ namespace Emby.Drawing
try
{
- Directory.CreateDirectory(Path.GetDirectoryName(enhancedImagePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(enhancedImagePath));
await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false);
diff --git a/MediaBrowser.Api/AppThemeService.cs b/MediaBrowser.Api/AppThemeService.cs
deleted file mode 100644
index 87084e415..000000000
--- a/MediaBrowser.Api/AppThemeService.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Themes;
-using MediaBrowser.Model.Themes;
-using ServiceStack;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace MediaBrowser.Api
-{
- [Route("/Themes", "GET", Summary = "Gets a list of available themes for an app")]
- public class GetAppThemes : IReturn<List<AppThemeInfo>>
- {
- [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string App { get; set; }
- }
-
- [Route("/Themes/Info", "GET", Summary = "Gets an app theme")]
- public class GetAppTheme : IReturn<AppTheme>
- {
- [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string App { get; set; }
-
- [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Name { get; set; }
- }
-
- [Route("/Themes/Images", "GET", Summary = "Gets an app theme")]
- public class GetAppThemeImage
- {
- [ApiMember(Name = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string App { get; set; }
-
- [ApiMember(Name = "Theme", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Theme { get; set; }
-
- [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Name { get; set; }
-
- [ApiMember(Name = "CacheTag", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string CacheTag { get; set; }
- }
-
- [Route("/Themes", "POST", Summary = "Saves a theme")]
- public class SaveTheme : AppTheme, IReturnVoid
- {
- }
-
- [Authenticated]
- public class AppThemeService : BaseApiService
- {
- private readonly IAppThemeManager _themeManager;
- private readonly IFileSystem _fileSystem;
-
- public AppThemeService(IAppThemeManager themeManager, IFileSystem fileSystem)
- {
- _themeManager = themeManager;
- _fileSystem = fileSystem;
- }
-
- public object Get(GetAppThemes request)
- {
- var result = _themeManager.GetThemes(request.App).ToList();
-
- return ToOptimizedResult(result);
- }
-
- public object Get(GetAppTheme request)
- {
- var result = _themeManager.GetTheme(request.App, request.Name);
-
- return ToOptimizedResult(result);
- }
-
- public void Post(SaveTheme request)
- {
- _themeManager.SaveTheme(request);
- }
-
- public object Get(GetAppThemeImage request)
- {
- var info = _themeManager.GetImageImageInfo(request.App, request.Theme, request.Name);
-
- var cacheGuid = new Guid(info.CacheTag);
-
- TimeSpan? cacheDuration = null;
-
- if (!string.IsNullOrEmpty(request.CacheTag) && cacheGuid == new Guid(request.CacheTag))
- {
- cacheDuration = TimeSpan.FromDays(365);
- }
-
- var contentType = MimeTypes.GetMimeType(info.Path);
-
- return ResultFactory.GetCachedResult(Request, cacheGuid, null, cacheDuration, () => _fileSystem.GetFileStream(info.Path, FileMode.Open, FileAccess.Read, FileShare.Read), contentType);
- }
- }
-}
diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs
index ab0a4a4b2..759eea353 100644
--- a/MediaBrowser.Api/Devices/DeviceService.cs
+++ b/MediaBrowser.Api/Devices/DeviceService.cs
@@ -1,4 +1,6 @@
-using MediaBrowser.Controller.Devices;
+using System;
+using System.Linq;
+using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Querying;
@@ -128,15 +130,32 @@ namespace MediaBrowser.Api.Devices
var id = Request.QueryString["Id"];
var name = Request.QueryString["Name"];
- var task = _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
+ if (Request.ContentType.IndexOf("multi", StringComparison.OrdinalIgnoreCase) == -1)
{
- MimeType = Request.ContentType,
- Album = album,
- Name = name,
- Id = id
- });
-
- Task.WaitAll(task);
+ var task = _deviceManager.AcceptCameraUpload(deviceId, request.RequestStream, new LocalFileInfo
+ {
+ MimeType = Request.ContentType,
+ Album = album,
+ Name = name,
+ Id = id
+ });
+
+ Task.WaitAll(task);
+ }
+ else
+ {
+ var file = Request.Files.First();
+
+ var task = _deviceManager.AcceptCameraUpload(deviceId, file.InputStream, new LocalFileInfo
+ {
+ MimeType = file.ContentType,
+ Album = album,
+ Name = name,
+ Id = id
+ });
+
+ Task.WaitAll(task);
+ }
}
}
}
diff --git a/MediaBrowser.Api/Dlna/DlnaServerService.cs b/MediaBrowser.Api/Dlna/DlnaServerService.cs
index 4f5e2ab25..4e7b1a7d5 100644
--- a/MediaBrowser.Api/Dlna/DlnaServerService.cs
+++ b/MediaBrowser.Api/Dlna/DlnaServerService.cs
@@ -108,7 +108,6 @@ namespace MediaBrowser.Api.Dlna
private readonly IConnectionManager _connectionManager;
private readonly IMediaReceiverRegistrar _mediaReceiverRegistrar;
- // TODO: Add utf-8
private const string XMLContentType = "text/xml; charset=UTF-8";
public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IMediaReceiverRegistrar mediaReceiverRegistrar)
diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs
index 457b4709b..11a0eec23 100644
--- a/MediaBrowser.Api/EnvironmentService.cs
+++ b/MediaBrowser.Api/EnvironmentService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
@@ -96,13 +97,14 @@ namespace MediaBrowser.Api
/// The _network manager
/// </summary>
private readonly INetworkManager _networkManager;
+ private IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="EnvironmentService" /> class.
/// </summary>
/// <param name="networkManager">The network manager.</param>
/// <exception cref="System.ArgumentNullException">networkManager</exception>
- public EnvironmentService(INetworkManager networkManager)
+ public EnvironmentService(INetworkManager networkManager, IFileSystem fileSystem)
{
if (networkManager == null)
{
@@ -110,6 +112,7 @@ namespace MediaBrowser.Api
}
_networkManager = networkManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -135,7 +138,15 @@ namespace MediaBrowser.Api
return ToOptimizedSerializedResultUsingCache(GetNetworkShares(path).OrderBy(i => i.Path).ToList());
}
- return ToOptimizedSerializedResultUsingCache(GetFileSystemEntries(request).OrderBy(i => i.Path).ToList());
+ try
+ {
+ return ToOptimizedSerializedResultUsingCache(GetFileSystemEntries(request).OrderBy(i => i.Path).ToList());
+ }
+ catch (UnauthorizedAccessException)
+ {
+ // Don't throw the original UnauthorizedAccessException because it will cause a 401 response
+ throw new ApplicationException("Access to the path " + request.Path + " is denied.");
+ }
}
public object Get(GetNetworkShares request)
@@ -222,8 +233,7 @@ namespace MediaBrowser.Api
private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
{
// using EnumerateFileSystemInfos doesn't handle reparse points (symlinks)
- var entries = new DirectoryInfo(request.Path).EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
- .Concat<FileSystemInfo>(new DirectoryInfo(request.Path).EnumerateFiles("*", SearchOption.TopDirectoryOnly)).Where(i =>
+ var entries = _fileSystem.GetFileSystemEntries(request.Path).Where(i =>
{
if (!request.IncludeHidden && i.Attributes.HasFlag(FileAttributes.Hidden))
{
diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs
index b4d5a9949..a6e1af516 100644
--- a/MediaBrowser.Api/Images/ImageByNameService.cs
+++ b/MediaBrowser.Api/Images/ImageByNameService.cs
@@ -130,8 +130,7 @@ namespace MediaBrowser.Api.Images
{
try
{
- return new DirectoryInfo(path)
- .GetFiles("*", SearchOption.AllDirectories)
+ return _fileSystem.GetFiles(path)
.Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.Ordinal))
.Select(i => new ImageByNameInfo
{
@@ -184,7 +183,7 @@ namespace MediaBrowser.Api.Images
var paths = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(_appPaths.GeneralPath, request.Name, filename + i)).ToList();
- var path = paths.FirstOrDefault(File.Exists) ?? paths.FirstOrDefault();
+ var path = paths.FirstOrDefault(_fileSystem.FileExists) ?? paths.FirstOrDefault();
return ToStaticFileResult(path);
}
@@ -198,11 +197,11 @@ namespace MediaBrowser.Api.Images
{
var themeFolder = Path.Combine(_appPaths.RatingsPath, request.Theme);
- if (Directory.Exists(themeFolder))
+ if (_fileSystem.DirectoryExists(themeFolder))
{
var path = BaseItem.SupportedImageExtensions
.Select(i => Path.Combine(themeFolder, request.Name + i))
- .FirstOrDefault(File.Exists);
+ .FirstOrDefault(_fileSystem.FileExists);
if (!string.IsNullOrEmpty(path))
{
@@ -212,14 +211,14 @@ namespace MediaBrowser.Api.Images
var allFolder = Path.Combine(_appPaths.RatingsPath, "all");
- if (Directory.Exists(allFolder))
+ if (_fileSystem.DirectoryExists(allFolder))
{
// Avoid implicitly captured closure
var currentRequest = request;
var path = BaseItem.SupportedImageExtensions
.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
- .FirstOrDefault(File.Exists);
+ .FirstOrDefault(_fileSystem.FileExists);
if (!string.IsNullOrEmpty(path))
{
@@ -239,10 +238,10 @@ namespace MediaBrowser.Api.Images
{
var themeFolder = Path.Combine(_appPaths.MediaInfoImagesPath, request.Theme);
- if (Directory.Exists(themeFolder))
+ if (_fileSystem.DirectoryExists(themeFolder))
{
var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, request.Name + i))
- .FirstOrDefault(File.Exists);
+ .FirstOrDefault(_fileSystem.FileExists);
if (!string.IsNullOrEmpty(path))
{
@@ -252,13 +251,13 @@ namespace MediaBrowser.Api.Images
var allFolder = Path.Combine(_appPaths.MediaInfoImagesPath, "all");
- if (Directory.Exists(allFolder))
+ if (_fileSystem.DirectoryExists(allFolder))
{
// Avoid implicitly captured closure
var currentRequest = request;
var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
- .FirstOrDefault(File.Exists);
+ .FirstOrDefault(_fileSystem.FileExists);
if (!string.IsNullOrEmpty(path))
{
diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs
index 6d2579ea9..c67ef96c9 100644
--- a/MediaBrowser.Api/Images/RemoteImageService.cs
+++ b/MediaBrowser.Api/Images/RemoteImageService.cs
@@ -237,7 +237,7 @@ namespace MediaBrowser.Api.Images
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
}
- if (File.Exists(contentPath))
+ if (_fileSystem.FileExists(contentPath))
{
return ToStaticFileResult(contentPath);
}
@@ -281,7 +281,7 @@ namespace MediaBrowser.Api.Images
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
- Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath));
using (var stream = result.Content)
{
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
@@ -290,7 +290,7 @@ namespace MediaBrowser.Api.Images
}
}
- Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
using (var writer = new StreamWriter(pointerCachePath))
{
await writer.WriteAsync(fullCachePath).ConfigureAwait(false);
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs
index a0ba6e61f..9f7f57155 100644
--- a/MediaBrowser.Api/ItemLookupService.cs
+++ b/MediaBrowser.Api/ItemLookupService.cs
@@ -200,7 +200,7 @@ namespace MediaBrowser.Api
//}
item.ProviderIds = request.ProviderIds;
- var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions
+ var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions(_fileSystem)
{
MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
ImageRefreshMode = ImageRefreshMode.FullRefresh,
@@ -230,7 +230,7 @@ namespace MediaBrowser.Api
contentPath = await reader.ReadToEndAsync().ConfigureAwait(false);
}
- if (File.Exists(contentPath))
+ if (_fileSystem.FileExists(contentPath))
{
return ToStaticFileResult(contentPath);
}
@@ -271,7 +271,7 @@ namespace MediaBrowser.Api
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
- Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath));
using (var stream = result.Content)
{
using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
@@ -280,7 +280,7 @@ namespace MediaBrowser.Api
}
}
- Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
using (var writer = new StreamWriter(pointerCachePath))
{
await writer.WriteAsync(fullCachePath).ConfigureAwait(false);
diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs
index f56fd3282..1e74b3692 100644
--- a/MediaBrowser.Api/ItemRefreshService.cs
+++ b/MediaBrowser.Api/ItemRefreshService.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers;
using ServiceStack;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Api
{
@@ -37,11 +38,13 @@ namespace MediaBrowser.Api
{
private readonly ILibraryManager _libraryManager;
private readonly IProviderManager _providerManager;
+ private readonly IFileSystem _fileSystem;
- public ItemRefreshService(ILibraryManager libraryManager, IProviderManager providerManager)
+ public ItemRefreshService(ILibraryManager libraryManager, IProviderManager providerManager, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
_providerManager = providerManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -66,7 +69,7 @@ namespace MediaBrowser.Api
private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request)
{
- return new MetadataRefreshOptions(new DirectoryService())
+ return new MetadataRefreshOptions(new DirectoryService(_fileSystem))
{
MetadataRefreshMode = request.MetadataRefreshMode,
ImageRefreshMode = request.ImageRefreshMode,
diff --git a/MediaBrowser.Api/Library/LibraryHelpers.cs b/MediaBrowser.Api/Library/LibraryHelpers.cs
index 0ee28d6fe..5e40ac635 100644
--- a/MediaBrowser.Api/Library/LibraryHelpers.cs
+++ b/MediaBrowser.Api/Library/LibraryHelpers.cs
@@ -33,7 +33,7 @@ namespace MediaBrowser.Api.Library
var rootFolderPath = appPaths.DefaultUserViewsPath;
var path = Path.Combine(rootFolderPath, virtualFolderName);
- if (!Directory.Exists(path))
+ if (!fileSystem.DirectoryExists(path))
{
throw new DirectoryNotFoundException(string.Format("The media collection {0} does not exist", virtualFolderName));
}
@@ -57,7 +57,7 @@ namespace MediaBrowser.Api.Library
/// <exception cref="System.ArgumentException">The path is not valid.</exception>
public static void AddMediaPath(IFileSystem fileSystem, string virtualFolderName, string path, IServerApplicationPaths appPaths)
{
- if (!Directory.Exists(path))
+ if (!fileSystem.DirectoryExists(path))
{
throw new DirectoryNotFoundException("The path does not exist.");
}
@@ -69,7 +69,7 @@ namespace MediaBrowser.Api.Library
var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
- while (File.Exists(lnk))
+ while (fileSystem.FileExists(lnk))
{
shortcutFilename += "1";
lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 49dd121ba..eb1cd6084 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -27,6 +27,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Api.Library
{
@@ -282,12 +283,13 @@ namespace MediaBrowser.Api.Library
private readonly IChannelManager _channelManager;
private readonly ITVSeriesManager _tvManager;
private readonly ILibraryMonitor _libraryMonitor;
+ private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="LibraryService" /> class.
/// </summary>
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
- IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, IChannelManager channelManager, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor)
+ IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, IChannelManager channelManager, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem)
{
_itemRepo = itemRepo;
_libraryManager = libraryManager;
@@ -301,6 +303,7 @@ namespace MediaBrowser.Api.Library
_channelManager = channelManager;
_tvManager = tvManager;
_libraryMonitor = libraryMonitor;
+ _fileSystem = fileSystem;
}
public object Get(GetSimilarItems request)
@@ -557,7 +560,7 @@ namespace MediaBrowser.Api.Library
{
throw new ArgumentException("This command cannot be used for remote or virtual items.");
}
- if (Directory.Exists(item.Path))
+ if (_fileSystem.DirectoryExists(item.Path))
{
throw new ArgumentException("This command cannot be used for directories.");
}
diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs
index f5fe921ce..c8731637c 100644
--- a/MediaBrowser.Api/Library/LibraryStructureService.cs
+++ b/MediaBrowser.Api/Library/LibraryStructureService.cs
@@ -195,7 +195,7 @@ namespace MediaBrowser.Api.Library
var virtualFolderPath = Path.Combine(rootFolderPath, name);
- if (Directory.Exists(virtualFolderPath))
+ if (_fileSystem.DirectoryExists(virtualFolderPath))
{
throw new ArgumentException("There is already a media collection with the name " + name + ".");
}
@@ -204,13 +204,16 @@ namespace MediaBrowser.Api.Library
try
{
- Directory.CreateDirectory(virtualFolderPath);
+ _fileSystem.CreateDirectory(virtualFolderPath);
if (!string.IsNullOrEmpty(request.CollectionType))
{
var path = Path.Combine(virtualFolderPath, request.CollectionType + ".collection");
- File.Create(path);
+ using (File.Create(path))
+ {
+
+ }
}
}
finally
@@ -256,12 +259,12 @@ namespace MediaBrowser.Api.Library
var currentPath = Path.Combine(rootFolderPath, request.Name);
var newPath = Path.Combine(rootFolderPath, request.NewName);
- if (!Directory.Exists(currentPath))
+ if (!_fileSystem.DirectoryExists(currentPath))
{
throw new DirectoryNotFoundException("The media collection does not exist");
}
- if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && Directory.Exists(newPath))
+ if (!string.Equals(currentPath, newPath, StringComparison.OrdinalIgnoreCase) && _fileSystem.DirectoryExists(newPath))
{
throw new ArgumentException("There is already a media collection with the name " + newPath + ".");
}
@@ -276,11 +279,11 @@ namespace MediaBrowser.Api.Library
//Create an unique name
var temporaryName = Guid.NewGuid().ToString();
var temporaryPath = Path.Combine(rootFolderPath, temporaryName);
- Directory.Move(currentPath, temporaryPath);
+ _fileSystem.MoveDirectory(currentPath, temporaryPath);
currentPath = temporaryPath;
}
- Directory.Move(currentPath, newPath);
+ _fileSystem.MoveDirectory(currentPath, newPath);
}
finally
{
@@ -319,7 +322,7 @@ namespace MediaBrowser.Api.Library
var path = Path.Combine(rootFolderPath, request.Name);
- if (!Directory.Exists(path))
+ if (!_fileSystem.DirectoryExists(path))
{
throw new DirectoryNotFoundException("The media folder does not exist");
}
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 295cc78e9..901dd11e2 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -11,10 +11,10 @@
<AssemblyName>MediaBrowser.Api</AssemblyName>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
- <ProductVersion>10.0.0</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<RestorePackages>true</RestorePackages>
+ <ReleaseVersion>
+ </ReleaseVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -25,7 +25,6 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@@ -34,7 +33,6 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Mono|AnyCPU' ">
<DebugType>none</DebugType>
@@ -43,16 +41,11 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
- <Reference Include="MoreLinq, Version=1.1.17511.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\morelinq.1.1.0\lib\net35\MoreLinq.dll</HintPath>
- </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
@@ -64,12 +57,14 @@
<Reference Include="ServiceStack.Text">
<HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
</Reference>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
- <Compile Include="AppThemeService.cs" />
<Compile Include="BrandingService.cs" />
<Compile Include="ChannelService.cs" />
<Compile Include="ConnectService.cs" />
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 531d67eed..86f06213c 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -290,13 +290,6 @@ namespace MediaBrowser.Api.Playback
{
get
{
- var lib = ApiEntryPoint.Instance.GetEncodingOptions().H264Encoder;
-
- if (!string.IsNullOrWhiteSpace(lib))
- {
- return lib;
- }
-
return "libx264";
}
}
@@ -810,13 +803,53 @@ namespace MediaBrowser.Api.Playback
}
/// <summary>
+ /// Gets the name of the output video codec
+ /// </summary>
+ /// <param name="state">The state.</param>
+ /// <returns>System.String.</returns>
+ protected string GetVideoDecoder(StreamState state)
+ {
+ if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareVideoDecoder, "qsv", StringComparison.OrdinalIgnoreCase))
+ {
+ if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec))
+ {
+ switch (state.MediaSource.VideoStream.Codec.ToLower())
+ {
+ case "avc":
+ case "h264":
+ if (MediaEncoder.SupportsDecoder("h264_qsv"))
+ {
+ return "-c:v h264_qsv ";
+ }
+ break;
+ case "mpeg2video":
+ if (MediaEncoder.SupportsDecoder("mpeg2_qsv"))
+ {
+ return "-c:v mpeg2_qsv ";
+ }
+ break;
+ case "vc1":
+ if (MediaEncoder.SupportsDecoder("vc1_qsv"))
+ {
+ return "-c:v vc1_qsv ";
+ }
+ break;
+ }
+ }
+ }
+
+ // leave blank so ffmpeg will decide
+ return string.Empty;
+ }
+
+ /// <summary>
/// Gets the input argument.
/// </summary>
/// <param name="state">The state.</param>
/// <returns>System.String.</returns>
protected string GetInputArgument(StreamState state)
{
- var arg = "-i " + GetInputPathArgument(state);
+ var arg = string.Format("{1}-i {0}", GetInputPathArgument(state), GetVideoDecoder(state));
if (state.SubtitleStream != null)
{
@@ -826,7 +859,7 @@ namespace MediaBrowser.Api.Playback
}
}
- return arg;
+ return arg.Trim();
}
private string GetInputPathArgument(StreamState state)
@@ -889,7 +922,7 @@ namespace MediaBrowser.Api.Playback
CancellationTokenSource cancellationTokenSource,
string workingDirectory = null)
{
- Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+ FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
@@ -942,7 +975,7 @@ namespace MediaBrowser.Api.Playback
Logger.Info(commandLineLogMessage);
var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, "transcode-" + Guid.NewGuid() + ".txt");
- Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
+ FileSystem.CreateDirectory(Path.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, FileMode.Create, FileAccess.Write, FileShare.Read, true);
@@ -972,7 +1005,7 @@ namespace MediaBrowser.Api.Playback
StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream);
// Wait for the file to exist before proceeeding
- while (!File.Exists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited)
+ while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited)
{
await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
index c201ffd58..cbee821d2 100644
--- a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
+++ b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
@@ -174,7 +174,7 @@ namespace MediaBrowser.Api.Playback.Dash
var workingDirectory = Path.Combine(Path.GetDirectoryName(playlistPath), (startNumber == -1 ? 0 : startNumber).ToString(CultureInfo.InvariantCulture));
state.WaitForPath = Path.Combine(workingDirectory, Path.GetFileName(playlistPath));
- Directory.CreateDirectory(workingDirectory);
+ FileSystem.CreateDirectory(workingDirectory);
job = await StartFfMpeg(state, playlistPath, cancellationTokenSource, workingDirectory).ConfigureAwait(false);
await WaitForMinimumDashSegmentCount(Path.Combine(workingDirectory, Path.GetFileName(playlistPath)), 1, cancellationTokenSource.Token).ConfigureAwait(false);
}
@@ -328,8 +328,7 @@ namespace MediaBrowser.Api.Playback.Dash
try
{
- return new DirectoryInfo(folder)
- .EnumerateFiles("*", SearchOption.AllDirectories)
+ return fileSystem.GetFiles(folder)
.Where(i => string.Equals(i.Extension, segmentExtension, StringComparison.OrdinalIgnoreCase))
.OrderByDescending(fileSystem.GetLastWriteTimeUtc)
.Take(count)
@@ -348,20 +347,20 @@ namespace MediaBrowser.Api.Playback.Dash
if (requestedIndex == -1)
{
var path = Path.Combine(folder, "0", "stream" + representationId + "-" + "init" + segmentExtension);
- return File.Exists(path) ? path : null;
+ return FileSystem.FileExists(path) ? path : null;
}
try
{
- foreach (var subfolder in new DirectoryInfo(folder).EnumerateDirectories().ToList())
+ foreach (var subfolder in FileSystem.GetDirectoryPaths(folder).ToList())
{
- var subfolderName = Path.GetFileNameWithoutExtension(subfolder.FullName);
+ var subfolderName = Path.GetFileNameWithoutExtension(subfolder);
int startNumber;
if (int.TryParse(subfolderName, NumberStyles.Any, UsCulture, out startNumber))
{
var segmentIndex = requestedIndex - startNumber + 1;
var path = Path.Combine(folder, subfolderName, "stream" + representationId + "-" + segmentIndex.ToString("00000", CultureInfo.InvariantCulture) + segmentExtension);
- if (File.Exists(path))
+ if (FileSystem.FileExists(path))
{
return path;
}
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 5d377366a..036397b4f 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -90,12 +90,12 @@ namespace MediaBrowser.Api.Playback.Hls
TranscodingJob job = null;
var playlist = state.OutputFilePath;
- if (!File.Exists(playlist))
+ if (!FileSystem.FileExists(playlist))
{
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
try
{
- if (!File.Exists(playlist))
+ if (!FileSystem.FileExists(playlist))
{
// If the playlist doesn't already exist, startup ffmpeg
try
@@ -312,31 +312,6 @@ namespace MediaBrowser.Api.Playback.Hls
return 0;
}
- protected override bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
- {
- if (videoStream.KeyFrames == null || videoStream.KeyFrames.Count == 0)
- {
- Logger.Debug("Cannot stream copy video due to missing keyframe info");
- return false;
- }
-
- var previousSegment = 0;
- foreach (var frame in videoStream.KeyFrames)
- {
- var length = frame - previousSegment;
-
- // Don't allow really long segments because this could result in long download times
- if (length > 10000)
- {
- Logger.Debug("Cannot stream copy video due to long segment length of {0}ms", length);
- return false;
- }
- previousSegment = frame;
- }
-
- return base.CanStreamCopyVideo(request, videoStream);
- }
-
protected override bool CanStreamCopyAudio(VideoStreamRequest request, MediaStream audioStream, List<string> supportedAudioCodecs)
{
return false;
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index cbea1ca0c..9359c65f2 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -165,7 +165,7 @@ namespace MediaBrowser.Api.Playback.Hls
TranscodingJob job = null;
- if (File.Exists(segmentPath))
+ if (FileSystem.FileExists(segmentPath))
{
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
@@ -174,7 +174,7 @@ namespace MediaBrowser.Api.Playback.Hls
await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
try
{
- if (File.Exists(segmentPath))
+ if (FileSystem.FileExists(segmentPath))
{
job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
return await GetSegmentResult(state, playlistPath, segmentPath, requestedIndex, job, cancellationToken).ConfigureAwait(false);
@@ -285,20 +285,23 @@ namespace MediaBrowser.Api.Playback.Hls
private double[] GetSegmentLengths(StreamState state)
{
var result = new List<double>();
- var encoder = GetVideoEncoder(state);
-
- if (string.Equals(encoder, "copy", StringComparison.OrdinalIgnoreCase))
+ if (state.VideoRequest != null)
{
- var videoStream = state.VideoStream;
- if (videoStream.KeyFrames != null && videoStream.KeyFrames.Count > 0)
+ var encoder = GetVideoEncoder(state);
+
+ if (string.Equals(encoder, "copy", StringComparison.OrdinalIgnoreCase))
{
- foreach (var frame in videoStream.KeyFrames)
+ var videoStream = state.VideoStream;
+ if (videoStream.KeyFrames != null && videoStream.KeyFrames.Count > 0)
{
- var seconds = TimeSpan.FromMilliseconds(frame).TotalSeconds;
- seconds -= result.Sum();
- result.Add(seconds);
+ foreach (var frame in videoStream.KeyFrames)
+ {
+ var seconds = TimeSpan.FromMilliseconds(frame).TotalSeconds;
+ seconds -= result.Sum();
+ result.Add(seconds);
+ }
+ return result.ToArray();
}
- return result.ToArray();
}
}
@@ -383,8 +386,7 @@ namespace MediaBrowser.Api.Playback.Hls
try
{
- return new DirectoryInfo(folder)
- .EnumerateFiles("*", SearchOption.TopDirectoryOnly)
+ return fileSystem.GetFiles(folder)
.Where(i => string.Equals(i.Extension, segmentExtension, StringComparison.OrdinalIgnoreCase) && Path.GetFileNameWithoutExtension(i.Name).StartsWith(filePrefix, StringComparison.OrdinalIgnoreCase))
.OrderByDescending(fileSystem.GetLastWriteTimeUtc)
.FirstOrDefault();
@@ -429,7 +431,7 @@ namespace MediaBrowser.Api.Playback.Hls
CancellationToken cancellationToken)
{
// If all transcoding has completed, just return immediately
- if (transcodingJob != null && transcodingJob.HasExited && File.Exists(segmentPath))
+ if (transcodingJob != null && transcodingJob.HasExited && FileSystem.FileExists(segmentPath))
{
return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
}
@@ -449,7 +451,7 @@ namespace MediaBrowser.Api.Playback.Hls
// If it appears in the playlist, it's done
if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1)
{
- if (File.Exists(segmentPath))
+ if (FileSystem.FileExists(segmentPath))
{
return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
}
@@ -960,5 +962,30 @@ namespace MediaBrowser.Api.Playback.Hls
{
return isOutputVideo ? ".ts" : ".ts";
}
+
+ protected override bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
+ {
+ if (videoStream.KeyFrames == null || videoStream.KeyFrames.Count == 0)
+ {
+ Logger.Debug("Cannot stream copy video due to missing keyframe info");
+ return false;
+ }
+
+ var previousSegment = 0;
+ foreach (var frame in videoStream.KeyFrames)
+ {
+ var length = frame - previousSegment;
+
+ // Don't allow really long segments because this could result in long download times
+ if (length > 10000)
+ {
+ Logger.Debug("Cannot stream copy video due to long segment length of {0}ms", length);
+ return false;
+ }
+ previousSegment = frame;
+ }
+
+ return base.CanStreamCopyVideo(request, videoStream);
+ }
}
}
diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs
index 0b7b50134..2ab2d11f6 100644
--- a/MediaBrowser.Api/Playback/MediaInfoService.cs
+++ b/MediaBrowser.Api/Playback/MediaInfoService.cs
@@ -57,7 +57,7 @@ namespace MediaBrowser.Api.Playback
Size = 102400;
}
}
-
+
[Authenticated]
public class MediaInfoService : BaseApiService
{
@@ -289,7 +289,7 @@ namespace MediaBrowser.Api.Playback
if (mediaSource.SupportsDirectStream)
{
options.MaxBitrate = GetMaxBitrate(maxBitrate);
-
+
// The MediaSource supports direct stream, now test to see if the client supports it
var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ?
streamBuilder.BuildAudioItem(options) :
@@ -309,7 +309,7 @@ namespace MediaBrowser.Api.Playback
if (mediaSource.SupportsTranscoding)
{
options.MaxBitrate = GetMaxBitrate(maxBitrate);
-
+
// The MediaSource supports direct stream, now test to see if the client supports it
var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ?
streamBuilder.BuildAudioItem(options) :
@@ -336,9 +336,15 @@ namespace MediaBrowser.Api.Playback
var maxBitrate = clientMaxBitrate;
var remoteClientMaxBitrate = _config.Configuration.RemoteClientBitrateLimit;
- if (remoteClientMaxBitrate > 0 && !_networkManager.IsInLocalNetwork(Request.RemoteIp))
+ if (remoteClientMaxBitrate > 0)
{
- maxBitrate = Math.Min(maxBitrate ?? remoteClientMaxBitrate, remoteClientMaxBitrate);
+ var isInLocalNetwork = _networkManager.IsInLocalNetwork(Request.RemoteIp);
+
+ Logger.Info("RemoteClientBitrateLimit: {0}, RemoteIp: {1}, IsInLocalNetwork: {2}", remoteClientMaxBitrate, Request.RemoteIp, isInLocalNetwork);
+ if (!isInLocalNetwork)
+ {
+ maxBitrate = Math.Min(maxBitrate ?? remoteClientMaxBitrate, remoteClientMaxBitrate);
+ }
}
return maxBitrate;
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index 910ac18e7..aa0cda133 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -139,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Progressive
}
var outputPath = state.OutputFilePath;
- var outputPathExists = File.Exists(outputPath);
+ var outputPathExists = FileSystem.FileExists(outputPath);
var isTranscodeCached = outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive);
@@ -325,7 +325,7 @@ namespace MediaBrowser.Api.Playback.Progressive
{
TranscodingJob job;
- if (!File.Exists(outputPath))
+ if (!FileSystem.FileExists(outputPath))
{
job = await StartFfMpeg(state, outputPath, cancellationTokenSource).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index 84ae26248..1dfb43387 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -17,6 +17,7 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <summary>
/// Class GetVideoStream
/// </summary>
+ [Route("/Videos/{Id}/stream.mpegts", "GET")]
[Route("/Videos/{Id}/stream.ts", "GET")]
[Route("/Videos/{Id}/stream.webm", "GET")]
[Route("/Videos/{Id}/stream.asf", "GET")]
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index 34dc5ea12..fdbe5835e 100644
--- a/MediaBrowser.Api/Playback/StreamState.cs
+++ b/MediaBrowser.Api/Playback/StreamState.cs
@@ -74,7 +74,7 @@ namespace MediaBrowser.Api.Playback
{
get
{
- return ReadInputAtNativeFramerate ? 1000 : 0;
+ return 0;
}
}
diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs b/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs
index c9ee6337f..fb694d6e1 100644
--- a/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs
+++ b/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs
@@ -213,7 +213,7 @@ namespace MediaBrowser.Api.Reports
};
foreach (var item in t)
{
- var ps = items.Where(x => x.People != null && x.SupportsPeople).SelectMany(x => x.People)
+ var ps = items.SelectMany(x => _libraryManager.GetPeople(x))
.Where(n => n.Type == item.ToString())
.GroupBy(x => x.Name)
.OrderByDescending(x => x.Count())
diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs
index e9ac45fa2..962334cdc 100644
--- a/MediaBrowser.Api/StartupWizardService.cs
+++ b/MediaBrowser.Api/StartupWizardService.cs
@@ -69,10 +69,10 @@ namespace MediaBrowser.Api
_config.Configuration.MergeMetadataAndImagesByName = true;
_config.Configuration.EnableStandaloneMetadata = true;
_config.Configuration.EnableLibraryMetadataSubFolder = true;
- _config.Configuration.EnableUserSpecificUserViews = true;
_config.Configuration.EnableCustomPathSubFolders = true;
_config.Configuration.DisableXmlSavers = true;
_config.Configuration.DisableStartupScan = true;
+ _config.Configuration.EnableUserViews = true;
_config.SaveConfiguration();
}
diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
index c9280b6f6..0bfe7354d 100644
--- a/MediaBrowser.Api/Subtitles/SubtitleService.cs
+++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs
@@ -16,6 +16,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Api.Subtitles
{
@@ -127,14 +128,16 @@ namespace MediaBrowser.Api.Subtitles
private readonly ISubtitleEncoder _subtitleEncoder;
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IProviderManager _providerManager;
+ private readonly IFileSystem _fileSystem;
- public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProviderManager providerManager)
+ public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProviderManager providerManager, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
_subtitleManager = subtitleManager;
_subtitleEncoder = subtitleEncoder;
_mediaSourceManager = mediaSourceManager;
_providerManager = providerManager;
+ _fileSystem = fileSystem;
}
public async Task<object> Get(GetSubtitlePlaylist request)
@@ -259,7 +262,7 @@ namespace MediaBrowser.Api.Subtitles
await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
.ConfigureAwait(false);
- _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions());
+ _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(_fileSystem));
}
catch (Exception ex)
{
diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs
index aa1226901..00935dd1e 100644
--- a/MediaBrowser.Api/System/SystemService.cs
+++ b/MediaBrowser.Api/System/SystemService.cs
@@ -122,8 +122,7 @@ namespace MediaBrowser.Api.System
try
{
- files = new DirectoryInfo(_appPaths.LogDirectoryPath)
- .EnumerateFiles("*", SearchOption.AllDirectories)
+ files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
.Where(i => string.Equals(i.Extension, ".txt", StringComparison.OrdinalIgnoreCase))
.ToList();
}
@@ -149,8 +148,7 @@ namespace MediaBrowser.Api.System
public object Get(GetLogFile request)
{
- var file = new DirectoryInfo(_appPaths.LogDirectoryPath)
- .EnumerateFiles("*", SearchOption.AllDirectories)
+ var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
.First(i => string.Equals(i.Name, request.Name, StringComparison.OrdinalIgnoreCase));
return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite);
diff --git a/MediaBrowser.Api/UserLibrary/UserViewsService.cs b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
index a49ab8556..9d7c38d6f 100644
--- a/MediaBrowser.Api/UserLibrary/UserViewsService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserViewsService.cs
@@ -39,6 +39,17 @@ namespace MediaBrowser.Api.UserLibrary
public string UserId { get; set; }
}
+ [Route("/Users/{UserId}/GroupingOptions", "GET")]
+ public class GetGroupingOptions : IReturn<List<SpecialViewOption>>
+ {
+ /// <summary>
+ /// Gets or sets the user id.
+ /// </summary>
+ /// <value>The user id.</value>
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string UserId { get; set; }
+ }
+
public class UserViewsService : BaseApiService
{
private readonly IUserManager _userManager;
@@ -105,6 +116,29 @@ namespace MediaBrowser.Api.UserLibrary
return ToOptimizedResult(list);
}
+ public async Task<object> Get(GetGroupingOptions request)
+ {
+ var user = _userManager.GetUserById(request.UserId);
+
+ var views = user.RootFolder
+ .GetChildren(user, true)
+ .OfType<Folder>()
+ .Where(i => !UserView.IsExcludedFromGrouping(i))
+ .ToList();
+
+ var list = views
+ .Select(i => new SpecialViewOption
+ {
+ Name = i.Name,
+ Id = i.Id.ToString("N")
+
+ })
+ .OrderBy(i => i.Name)
+ .ToList();
+
+ return ToOptimizedResult(list);
+ }
+
private bool IsEligibleForSpecialView(ICollectionFolder view)
{
var types = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Games, CollectionType.Music, CollectionType.Photos };
diff --git a/MediaBrowser.Api/packages.config b/MediaBrowser.Api/packages.config
index 6df166204..0cdb26bd5 100644
--- a/MediaBrowser.Api/packages.config
+++ b/MediaBrowser.Api/packages.config
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="morelinq" version="1.1.0" targetFramework="net45" />
+ <package id="morelinq" version="1.1.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs b/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs
index cdcbc311a..1377e9d55 100644
--- a/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs
+++ b/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs
@@ -7,6 +7,7 @@ using SharpCompress.Reader;
using SharpCompress.Reader.Zip;
using System;
using System.IO;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Common.Implementations.Archiving
{
@@ -15,7 +16,14 @@ namespace MediaBrowser.Common.Implementations.Archiving
/// </summary>
public class ZipClient : IZipClient
{
- /// <summary>
+ private IFileSystem _fileSystem;
+
+ public ZipClient(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
+ /// <summary>
/// Extracts all.
/// </summary>
/// <param name="sourceFile">The source file.</param>
@@ -23,7 +31,7 @@ namespace MediaBrowser.Common.Implementations.Archiving
/// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param>
public void ExtractAll(string sourceFile, string targetPath, bool overwriteExistingFiles)
{
- using (var fileStream = File.OpenRead(sourceFile))
+ using (var fileStream = _fileSystem.OpenRead(sourceFile))
{
ExtractAll(fileStream, targetPath, overwriteExistingFiles);
}
@@ -73,7 +81,7 @@ namespace MediaBrowser.Common.Implementations.Archiving
/// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param>
public void ExtractAllFrom7z(string sourceFile, string targetPath, bool overwriteExistingFiles)
{
- using (var fileStream = File.OpenRead(sourceFile))
+ using (var fileStream = _fileSystem.OpenRead(sourceFile))
{
ExtractAllFrom7z(fileStream, targetPath, overwriteExistingFiles);
}
@@ -112,7 +120,7 @@ namespace MediaBrowser.Common.Implementations.Archiving
/// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param>
public void ExtractAllFromTar(string sourceFile, string targetPath, bool overwriteExistingFiles)
{
- using (var fileStream = File.OpenRead(sourceFile))
+ using (var fileStream = _fileSystem.OpenRead(sourceFile))
{
ExtractAllFromTar(fileStream, targetPath, overwriteExistingFiles);
}
@@ -150,7 +158,7 @@ namespace MediaBrowser.Common.Implementations.Archiving
/// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param>
public void ExtractAllFromRar(string sourceFile, string targetPath, bool overwriteExistingFiles)
{
- using (var fileStream = File.OpenRead(sourceFile))
+ using (var fileStream = _fileSystem.OpenRead(sourceFile))
{
ExtractAllFromRar(fileStream, targetPath, overwriteExistingFiles);
}
diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
index 70ed5c319..af41635f3 100644
--- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
+++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
@@ -93,7 +93,7 @@ namespace MediaBrowser.Common.Implementations
/// <summary>
/// The _XML serializer
/// </summary>
- protected readonly IXmlSerializer XmlSerializer = new XmlSerializer();
+ protected readonly IXmlSerializer XmlSerializer;
/// <summary>
/// Gets assemblies that failed to load
@@ -180,7 +180,7 @@ namespace MediaBrowser.Common.Implementations
{
if (_deviceId == null)
{
- _deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId"));
+ _deviceId = new DeviceId(ApplicationPaths, LogManager.GetLogger("SystemId"), FileSystemManager);
}
return _deviceId.Value;
@@ -199,6 +199,7 @@ namespace MediaBrowser.Common.Implementations
ILogManager logManager,
IFileSystem fileSystem)
{
+ XmlSerializer = new MediaBrowser.Common.Implementations.Serialization.XmlSerializer (fileSystem);
FailedAssemblies = new List<string>();
ApplicationPaths = applicationPaths;
@@ -320,7 +321,7 @@ namespace MediaBrowser.Common.Implementations
protected virtual IJsonSerializer CreateJsonSerializer()
{
- return new JsonSerializer();
+ return new JsonSerializer(FileSystemManager);
}
private void SetHttpLimit()
@@ -449,7 +450,7 @@ namespace MediaBrowser.Common.Implementations
RegisterSingleInstance<IApplicationPaths>(ApplicationPaths);
- TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, Logger);
+ TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, Logger, FileSystemManager);
RegisterSingleInstance(JsonSerializer);
RegisterSingleInstance(XmlSerializer);
@@ -473,7 +474,7 @@ namespace MediaBrowser.Common.Implementations
InstallationManager = new InstallationManager(Logger, this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, ConfigurationManager, FileSystemManager);
RegisterSingleInstance(InstallationManager);
- ZipClient = new ZipClient();
+ ZipClient = new ZipClient(FileSystemManager);
RegisterSingleInstance(ZipClient);
IsoManager = new IsoManager();
@@ -581,7 +582,7 @@ namespace MediaBrowser.Common.Implementations
protected void RegisterSingleInstance<T>(T obj, bool manageLifetime = true)
where T : class
{
- Container.RegisterSingle(obj);
+ Container.RegisterSingleton(obj);
if (manageLifetime)
{
@@ -607,7 +608,7 @@ namespace MediaBrowser.Common.Implementations
protected void RegisterSingleInstance<T>(Func<T> func)
where T : class
{
- Container.RegisterSingle(func);
+ Container.RegisterSingleton(func);
}
void IDependencyContainer.Register(Type typeInterface, Type typeImplementation)
diff --git a/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs b/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs
index ff5b8bd59..276da58d4 100644
--- a/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs
+++ b/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs
@@ -2,6 +2,7 @@
using System;
using System.IO;
using System.Linq;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Common.Implementations.Configuration
{
@@ -27,7 +28,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
// Use try/catch to avoid the extra file system lookup using File.Exists
try
{
- buffer = File.ReadAllBytes(path);
+ buffer = File.ReadAllBytes(path);
configuration = xmlSerializer.DeserializeFromBytes(type, buffer);
}
@@ -46,10 +47,10 @@ namespace MediaBrowser.Common.Implementations.Configuration
// If the file didn't exist before, or if something has changed, re-save
if (buffer == null || !buffer.SequenceEqual(newBytes))
{
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
// Save it after load in case we got new items
- File.WriteAllBytes(path, newBytes);
+ File.WriteAllBytes(path, newBytes);
}
return configuration;
diff --git a/MediaBrowser.Common.Implementations/Devices/DeviceId.cs b/MediaBrowser.Common.Implementations/Devices/DeviceId.cs
index 2a1c8877d..39f11fabf 100644
--- a/MediaBrowser.Common.Implementations/Devices/DeviceId.cs
+++ b/MediaBrowser.Common.Implementations/Devices/DeviceId.cs
@@ -3,13 +3,15 @@ using MediaBrowser.Model.Logging;
using System;
using System.IO;
using System.Text;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Common.Implementations.Devices
{
public class DeviceId
{
private readonly IApplicationPaths _appPaths;
- private readonly ILogger _logger;
+ private readonly ILogger _logger;
+ private readonly IFileSystem _fileSystem;
private readonly object _syncLock = new object();
@@ -24,7 +26,7 @@ namespace MediaBrowser.Common.Implementations.Devices
{
lock (_syncLock)
{
- var value = File.ReadAllText(CachePath, Encoding.UTF8);
+ var value = File.ReadAllText(CachePath, Encoding.UTF8);
Guid guid;
if (Guid.TryParse(value, out guid))
@@ -55,11 +57,11 @@ namespace MediaBrowser.Common.Implementations.Devices
{
var path = CachePath;
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
lock (_syncLock)
{
- File.WriteAllText(path, id, Encoding.UTF8);
+ _fileSystem.WriteAllText(path, id, Encoding.UTF8);
}
}
catch (Exception ex)
@@ -88,10 +90,15 @@ namespace MediaBrowser.Common.Implementations.Devices
private string _id;
- public DeviceId(IApplicationPaths appPaths, ILogger logger)
+ public DeviceId(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
{
+ if (fileSystem == null) {
+ throw new ArgumentNullException ("fileSystem");
+ }
+
_appPaths = appPaths;
_logger = logger;
+ _fileSystem = fileSystem;
}
public string Value
diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
index 89f405e8a..7157f6325 100644
--- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
+++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
@@ -355,7 +355,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
private async Task CacheResponse(HttpResponseInfo response, string responseCachePath)
{
- Directory.CreateDirectory(Path.GetDirectoryName(responseCachePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(responseCachePath));
using (var responseStream = response.Content)
{
@@ -599,7 +599,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
{
ValidateParams(options);
- Directory.CreateDirectory(_appPaths.TempDirectory);
+ _fileSystem.CreateDirectory(_appPaths.TempDirectory);
var tempFile = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".tmp");
@@ -869,25 +869,11 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
Task<WebResponse> asyncTask = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null);
ThreadPool.RegisterWaitForSingleObject((asyncTask as IAsyncResult).AsyncWaitHandle, TimeoutCallback, request, timeout, true);
- asyncTask.ContinueWith(task =>
- {
- taskCompletion.TrySetResult(task.Result);
-
- }, TaskContinuationOptions.NotOnFaulted);
+ var callback = new TaskCallback { taskCompletion = taskCompletion };
+ asyncTask.ContinueWith(callback.OnSuccess, TaskContinuationOptions.NotOnFaulted);
// Handle errors
- asyncTask.ContinueWith(task =>
- {
- if (task.Exception != null)
- {
- taskCompletion.TrySetException(task.Exception);
- }
- else
- {
- taskCompletion.TrySetException(new List<Exception>());
- }
-
- }, TaskContinuationOptions.OnlyOnFaulted);
+ asyncTask.ContinueWith(callback.OnError, TaskContinuationOptions.OnlyOnFaulted);
return taskCompletion.Task;
}
@@ -903,5 +889,27 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
}
}
}
+
+ private class TaskCallback
+ {
+ public TaskCompletionSource<WebResponse> taskCompletion;
+
+ public void OnSuccess(Task<WebResponse> task)
+ {
+ taskCompletion.TrySetResult(task.Result);
+ }
+
+ public void OnError(Task<WebResponse> task)
+ {
+ if (task.Exception != null)
+ {
+ taskCompletion.TrySetException(task.Exception);
+ }
+ else
+ {
+ taskCompletion.TrySetException(new List<Exception>());
+ }
+ }
+ }
}
}
diff --git a/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
index e9ef84663..b899e88c2 100644
--- a/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
+++ b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
@@ -4,6 +4,8 @@ using MediaBrowser.Model.Logging;
using System;
using System.IO;
using System.Text;
+using System.Collections.Generic;
+using System.Linq;
namespace MediaBrowser.Common.Implementations.IO
{
@@ -75,7 +77,7 @@ namespace MediaBrowser.Common.Implementations.IO
if (string.Equals(Path.GetExtension(filename), ".mblink", StringComparison.OrdinalIgnoreCase))
{
- var path = File.ReadAllText(filename);
+ var path = ReadAllText(filename);
return NormalizePath(path);
}
@@ -105,7 +107,7 @@ namespace MediaBrowser.Common.Implementations.IO
throw new ArgumentNullException("target");
}
- File.WriteAllText(shortcutPath, target);
+ File.WriteAllText(shortcutPath, target);
}
/// <summary>
@@ -230,7 +232,7 @@ namespace MediaBrowser.Common.Implementations.IO
/// <param name="share">The share.</param>
/// <param name="isAsync">if set to <c>true</c> [is asynchronous].</param>
/// <returns>FileStream.</returns>
- public FileStream GetFileStream(string path, FileMode mode, FileAccess access, FileShare share, bool isAsync = false)
+ public Stream GetFileStream(string path, FileMode mode, FileAccess access, FileShare share, bool isAsync = false)
{
if (_supportsAsyncFileStreams && isAsync)
{
@@ -264,11 +266,11 @@ namespace MediaBrowser.Common.Implementations.IO
RemoveHiddenAttribute(file1);
RemoveHiddenAttribute(file2);
- File.Copy(file1, temp1, true);
- File.Copy(file2, temp2, true);
+ CopyFile(file1, temp1, true);
+ CopyFile(file2, temp2, true);
- File.Copy(temp1, file2, true);
- File.Copy(temp2, file1, true);
+ CopyFile(temp1, file2, true);
+ CopyFile(temp2, file1, true);
DeleteFile(temp1);
DeleteFile(temp2);
@@ -410,24 +412,110 @@ namespace MediaBrowser.Common.Implementations.IO
//return Path.IsPathRooted(path);
}
- public void DeleteFile(string path, bool sendToRecycleBin)
+ public void DeleteFile(string path)
{
File.Delete(path);
}
- public void DeleteDirectory(string path, bool recursive, bool sendToRecycleBin)
+ public void DeleteDirectory(string path, bool recursive)
{
Directory.Delete(path, recursive);
+ }
+
+ public void CreateDirectory(string path)
+ {
+ Directory.CreateDirectory(path);
+ }
+
+ public IEnumerable<DirectoryInfo> GetDirectories(string path, bool recursive = false)
+ {
+ var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+
+ return new DirectoryInfo (path).EnumerateDirectories("*", searchOption);
+ }
+
+ public IEnumerable<FileInfo> GetFiles(string path, bool recursive = false)
+ {
+ var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+
+ return new DirectoryInfo (path).EnumerateFiles("*", searchOption);
+ }
+
+ public IEnumerable<FileSystemInfo> GetFileSystemEntries(string path, bool recursive = false)
+ {
+ var directoryInfo = new DirectoryInfo (path);
+ var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+
+ return directoryInfo.EnumerateDirectories("*", searchOption)
+ .Concat<FileSystemInfo>(directoryInfo.EnumerateFiles("*", searchOption));
+ }
+
+ public Stream OpenRead(string path)
+ {
+ return File.OpenRead(path);
}
- public void DeleteFile(string path)
+ public void CopyFile(string source, string target, bool overwrite)
{
- DeleteFile(path, false);
+ File.Copy(source, target, overwrite);
}
- public void DeleteDirectory(string path, bool recursive)
+ public void MoveFile(string source, string target)
+ {
+ File.Move(source, target);
+ }
+
+ public void MoveDirectory(string source, string target)
+ {
+ Directory.Move(source, target);
+ }
+
+ public bool DirectoryExists(string path)
+ {
+ return Directory.Exists(path);
+ }
+
+ public bool FileExists(string path)
+ {
+ return File.Exists(path);
+ }
+
+ public string ReadAllText(string path)
+ {
+ return File.ReadAllText(path);
+ }
+
+ public void WriteAllText(string path, string text, Encoding encoding)
+ {
+ File.WriteAllText(path, text, encoding);
+ }
+
+ public void WriteAllText(string path, string text)
+ {
+ File.WriteAllText(path, text);
+ }
+
+ public string ReadAllText(string path, Encoding encoding)
+ {
+ return File.ReadAllText(path, encoding);
+ }
+
+ public IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false)
+ {
+ var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+ return Directory.EnumerateDirectories(path, "*", searchOption);
+ }
+
+ public IEnumerable<string> GetFilePaths(string path, bool recursive = false)
+ {
+ var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+ return Directory.EnumerateFiles(path, "*", searchOption);
+ }
+
+ public IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false)
{
- DeleteDirectory(path, recursive, false);
+ var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+ return Directory.EnumerateFileSystemEntries(path, "*", searchOption);
}
}
}
diff --git a/MediaBrowser.Common.Implementations/Logging/NlogManager.cs b/MediaBrowser.Common.Implementations/Logging/NlogManager.cs
index 698792802..391e7c212 100644
--- a/MediaBrowser.Common.Implementations/Logging/NlogManager.cs
+++ b/MediaBrowser.Common.Implementations/Logging/NlogManager.cs
@@ -170,7 +170,7 @@ namespace MediaBrowser.Common.Implementations.Logging
/// </summary>
/// <param name="name">The name.</param>
/// <returns>ILogger.</returns>
- public ILogger GetLogger(string name)
+ public Model.Logging.ILogger GetLogger(string name)
{
return new NLogger(name, this);
}
@@ -208,7 +208,7 @@ namespace MediaBrowser.Common.Implementations.Logging
{
LogFilePath = Path.Combine(LogDirectory, LogFilePrefix + "-" + decimal.Round(DateTime.Now.Ticks / 10000000) + ".txt");
- Directory.CreateDirectory(Path.GetDirectoryName(LogFilePath));
+ Directory.CreateDirectory(Path.GetDirectoryName(LogFilePath));
AddFileTarget(LogFilePath, level);
diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
index e603ea373..eb1122902 100644
--- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
+++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
@@ -48,18 +48,17 @@
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
- <Reference Include="NLog, Version=3.2.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
+ <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\NLog.3.2.1\lib\net45\NLog.dll</HintPath>
+ <HintPath>..\packages\NLog.4.1.1\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="SharpCompress, Version=0.10.2.0, Culture=neutral, PublicKeyToken=beaf6f427e128133, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
</Reference>
- <Reference Include="SimpleInjector, Version=2.7.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
+ <Reference Include="SimpleInjector, Version=2.8.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\SimpleInjector.2.8.0\lib\net45\SimpleInjector.dll</HintPath>
- <Private>True</Private>
+ <HintPath>..\packages\SimpleInjector.3.0.5\lib\net45\SimpleInjector.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
index cbd1c1ac5..906184c75 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
@@ -12,6 +12,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Common.Implementations.ScheduledTasks
{
@@ -51,6 +52,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// </summary>
/// <value>The task manager.</value>
private ITaskManager TaskManager { get; set; }
+ private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class.
@@ -71,7 +73,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// or
/// logger
/// </exception>
- public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger)
+ public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem)
{
if (scheduledTask == null)
{
@@ -99,6 +101,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
TaskManager = taskManager;
JsonSerializer = jsonSerializer;
Logger = logger;
+ _fileSystem = fileSystem;
ReloadTriggerEvents(true);
}
@@ -154,7 +157,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
_lastExecutionResult = value;
var path = GetHistoryFilePath();
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
lock (_lastExecutionResultSyncLock)
{
@@ -552,7 +555,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
{
var path = GetConfigurationFilePath();
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
JsonSerializer.SerializeToFile(triggers.Select(ScheduledTaskHelpers.GetTriggerInfo), path);
}
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
index de7987bd2..9419bdf22 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
@@ -10,6 +10,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Common.Implementations.ScheduledTasks
{
@@ -50,6 +51,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// </summary>
/// <value>The logger.</value>
private ILogger Logger { get; set; }
+ private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="TaskManager" /> class.
@@ -58,11 +60,12 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="logger">The logger.</param>
/// <exception cref="System.ArgumentException">kernel</exception>
- public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger)
+ public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger, IFileSystem fileSystem)
{
ApplicationPaths = applicationPaths;
JsonSerializer = jsonSerializer;
Logger = logger;
+ _fileSystem = fileSystem;
ScheduledTasks = new IScheduledTaskWorker[] { };
}
@@ -106,9 +109,16 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
public void QueueScheduledTask<T>(TaskExecutionOptions options)
where T : IScheduledTask
{
- var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T));
+ var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == typeof(T));
- QueueScheduledTask(scheduledTask, options);
+ if (scheduledTask == null)
+ {
+ Logger.Error("Unable to find scheduled task of type {0} in QueueScheduledTask.", typeof(T).Name);
+ }
+ else
+ {
+ QueueScheduledTask(scheduledTask, options);
+ }
}
public void QueueScheduledTask<T>()
@@ -124,9 +134,16 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <param name="options">The task options.</param>
public void QueueScheduledTask(IScheduledTask task, TaskExecutionOptions options)
{
- var scheduledTask = ScheduledTasks.First(t => t.ScheduledTask.GetType() == task.GetType());
+ var scheduledTask = ScheduledTasks.FirstOrDefault(t => t.ScheduledTask.GetType() == task.GetType());
- QueueScheduledTask(scheduledTask, options);
+ if (scheduledTask == null)
+ {
+ Logger.Error("Unable to find scheduled task of type {0} in QueueScheduledTask.", task.GetType().Name);
+ }
+ else
+ {
+ QueueScheduledTask(scheduledTask, options);
+ }
}
/// <summary>
@@ -161,7 +178,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
var myTasks = ScheduledTasks.ToList();
var list = tasks.ToList();
- myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger)));
+ myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem)));
ScheduledTasks = myTasks.ToArray();
}
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
index d9c178d8b..6d5516ebd 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
@@ -95,7 +95,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
/// <param name="progress">The progress.</param>
private void DeleteCacheFilesFromDirectory(CancellationToken cancellationToken, string directory, DateTime minDateModified, IProgress<double> progress)
{
- var filesToDelete = new DirectoryInfo(directory).EnumerateFiles("*", SearchOption.AllDirectories)
+ var filesToDelete = _fileSystem.GetFiles(directory, true)
.Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
.ToList();
@@ -120,14 +120,14 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
progress.Report(100);
}
- private static void DeleteEmptyFolders(string parent)
+ private void DeleteEmptyFolders(string parent)
{
foreach (var directory in Directory.GetDirectories(parent))
{
DeleteEmptyFolders(directory);
if (!Directory.EnumerateFileSystemEntries(directory).Any())
{
- Directory.Delete(directory, false);
+ _fileSystem.DeleteDirectory(directory, false);
}
}
}
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
index b2759c52a..ffba3d9da 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
@@ -58,7 +58,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
// Delete log files more than n days old
var minDateModified = DateTime.UtcNow.AddDays(-(ConfigurationManager.CommonConfiguration.LogFileRetentionDays));
- var filesToDelete = new DirectoryInfo(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath).EnumerateFileSystemInfos("*", SearchOption.AllDirectories)
+ var filesToDelete = _fileSystem.GetFiles(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath, true)
.Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
.ToList();
diff --git a/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs b/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs
index 63381efcd..79e558794 100644
--- a/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs
+++ b/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs
@@ -99,7 +99,7 @@ namespace MediaBrowser.Common.Implementations.Security
{
try
{
- contents = File.ReadAllLines(licenseFile);
+ contents = File.ReadAllLines(licenseFile);
}
catch (DirectoryNotFoundException)
{
@@ -107,7 +107,7 @@ namespace MediaBrowser.Common.Implementations.Security
}
catch (FileNotFoundException)
{
- (File.Create(licenseFile)).Close();
+ (File.Create(licenseFile)).Close();
}
}
if (contents != null && contents.Length > 0)
@@ -150,8 +150,8 @@ namespace MediaBrowser.Common.Implementations.Security
}
var licenseFile = Filename;
- Directory.CreateDirectory(Path.GetDirectoryName(licenseFile));
- lock (_fileLock) File.WriteAllLines(licenseFile, lines);
+ Directory.CreateDirectory(Path.GetDirectoryName(licenseFile));
+ lock (_fileLock) File.WriteAllLines(licenseFile, lines);
}
}
}
diff --git a/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs b/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs
index f194b334a..a758a0c1e 100644
--- a/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs
+++ b/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Serialization;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.Serialization;
using System;
using System.IO;
@@ -9,8 +10,11 @@ namespace MediaBrowser.Common.Implementations.Serialization
/// </summary>
public class JsonSerializer : IJsonSerializer
{
- public JsonSerializer()
+ private readonly IFileSystem _fileSystem;
+
+ public JsonSerializer(IFileSystem fileSystem)
{
+ _fileSystem = fileSystem;
Configure();
}
@@ -53,7 +57,7 @@ namespace MediaBrowser.Common.Implementations.Serialization
throw new ArgumentNullException("file");
}
- using (Stream stream = File.Open(file, FileMode.Create))
+ using (Stream stream = _fileSystem.GetFileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read))
{
SerializeToStream(obj, stream);
}
diff --git a/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs b/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs
index 04030522f..41a59fb2b 100644
--- a/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs
+++ b/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs
@@ -3,6 +3,7 @@ using System;
using System.Collections.Concurrent;
using System.IO;
using System.Xml;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Common.Implementations.Serialization
{
@@ -11,6 +12,13 @@ namespace MediaBrowser.Common.Implementations.Serialization
/// </summary>
public class XmlSerializer : IXmlSerializer
{
+ private IFileSystem _fileSystem;
+
+ public XmlSerializer(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
// Need to cache these
// http://dotnetcodebox.blogspot.com/2013/01/xmlserializer-class-may-result-in.html
private readonly ConcurrentDictionary<string, System.Xml.Serialization.XmlSerializer> _serializers =
@@ -83,7 +91,7 @@ namespace MediaBrowser.Common.Implementations.Serialization
/// <returns>System.Object.</returns>
public object DeserializeFromFile(Type type, string file)
{
- using (var stream = File.OpenRead(file))
+ using (var stream = _fileSystem.OpenRead(file))
{
return DeserializeFromStream(type, stream);
}
diff --git a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
index 5f205d69e..12afdd8d7 100644
--- a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
+++ b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
@@ -553,7 +553,7 @@ namespace MediaBrowser.Common.Implementations.Updates
if (packageChecksum != Guid.Empty) // support for legacy uploads for now
{
using (var crypto = new MD5CryptoServiceProvider())
- using (var stream = new BufferedStream(File.OpenRead(tempFile), 100000))
+ using (var stream = new BufferedStream(_fileSystem.OpenRead(tempFile), 100000))
{
var check = Guid.Parse(BitConverter.ToString(crypto.ComputeHash(stream)).Replace("-", String.Empty));
if (check != packageChecksum)
@@ -568,12 +568,12 @@ namespace MediaBrowser.Common.Implementations.Updates
// Success - move it to the real target
try
{
- Directory.CreateDirectory(Path.GetDirectoryName(target));
- File.Copy(tempFile, target, true);
+ _fileSystem.CreateDirectory(Path.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)
{
- File.WriteAllText(target + ".ver", package.versionStr);
+ File.WriteAllText(target + ".ver", package.versionStr);
}
}
catch (IOException e)
diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config
index e57c874f2..151a3a36d 100644
--- a/MediaBrowser.Common.Implementations/packages.config
+++ b/MediaBrowser.Common.Implementations/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="NLog" version="3.2.1" targetFramework="net45" />
- <package id="SimpleInjector" version="2.8.0" targetFramework="net45" />
+ <package id="NLog" version="4.1.0" targetFramework="net45" />
+ <package id="SimpleInjector" version="3.0.5" targetFramework="net45" />
</packages>
diff --git a/MediaBrowser.Common/IO/IFileSystem.cs b/MediaBrowser.Common/IO/IFileSystem.cs
index 5ce84f436..ce15ad999 100644
--- a/MediaBrowser.Common/IO/IFileSystem.cs
+++ b/MediaBrowser.Common/IO/IFileSystem.cs
@@ -1,5 +1,7 @@
using System;
using System.IO;
+using System.Collections.Generic;
+using System.Text;
namespace MediaBrowser.Common.IO
{
@@ -73,7 +75,9 @@ namespace MediaBrowser.Common.IO
/// <param name="share">The share.</param>
/// <param name="isAsync">if set to <c>true</c> [is asynchronous].</param>
/// <returns>FileStream.</returns>
- FileStream GetFileStream(string path, FileMode mode, FileAccess access, FileShare share, bool isAsync = false);
+ Stream GetFileStream(string path, FileMode mode, FileAccess access, FileShare share, bool isAsync = false);
+
+ Stream OpenRead(String path);
/// <summary>
/// Swaps the files.
@@ -138,21 +142,6 @@ namespace MediaBrowser.Common.IO
/// Deletes the file.
/// </summary>
/// <param name="path">The path.</param>
- /// <param name="sendToRecycleBin">if set to <c>true</c> [send to recycle bin].</param>
- void DeleteFile(string path, bool sendToRecycleBin);
-
- /// <summary>
- /// Deletes the directory.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="recursive">if set to <c>true</c> [recursive].</param>
- /// <param name="sendToRecycleBin">if set to <c>true</c> [send to recycle bin].</param>
- void DeleteDirectory(string path, bool recursive, bool sendToRecycleBin);
-
- /// <summary>
- /// Deletes the file.
- /// </summary>
- /// <param name="path">The path.</param>
void DeleteFile(string path);
/// <summary>
@@ -161,5 +150,37 @@ namespace MediaBrowser.Common.IO
/// <param name="path">The path.</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
void DeleteDirectory(string path, bool recursive);
+
+ IEnumerable<DirectoryInfo> GetDirectories(string path, bool recursive = false);
+
+ IEnumerable<FileInfo> GetFiles(string path, bool recursive = false);
+
+ IEnumerable<FileSystemInfo> GetFileSystemEntries(string path, bool recursive = false);
+
+ void CreateDirectory(string path);
+
+ void CopyFile(string source, string target, bool overwrite);
+
+ void MoveFile(string source, string target);
+
+ void MoveDirectory(string source, string target);
+
+ bool DirectoryExists(string path);
+
+ bool FileExists(string path);
+
+ string ReadAllText(string path);
+
+ void WriteAllText(string path, string text);
+
+ void WriteAllText(string path, string text, Encoding encoding);
+
+ string ReadAllText(string path, Encoding encoding);
+
+ IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false);
+
+ IEnumerable<string> GetFilePaths(string path, bool recursive = false);
+
+ IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false);
}
}
diff --git a/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs b/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs
index b615adf81..42871866d 100644
--- a/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs
+++ b/MediaBrowser.Common/ScheduledTasks/IntervalTrigger.cs
@@ -58,7 +58,7 @@ namespace MediaBrowser.Common.ScheduledTasks
{
if (isApplicationStartup)
{
- triggerDate = DateTime.UtcNow.AddMinutes(5);
+ triggerDate = DateTime.UtcNow.AddMinutes(2);
}
else
{
diff --git a/MediaBrowser.Controller/Channels/IChannelFactory.cs b/MediaBrowser.Controller/Channels/IChannelFactory.cs
deleted file mode 100644
index c7ed92586..000000000
--- a/MediaBrowser.Controller/Channels/IChannelFactory.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Collections.Generic;
-
-namespace MediaBrowser.Controller.Channels
-{
- public interface IChannelFactory
- {
- IEnumerable<IChannel> GetChannels();
- }
-
- public interface IFactoryChannel
- {
-
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs
index 8d3e0f596..fec550df8 100644
--- a/MediaBrowser.Controller/Channels/IChannelManager.cs
+++ b/MediaBrowser.Controller/Channels/IChannelManager.cs
@@ -16,7 +16,7 @@ namespace MediaBrowser.Controller.Channels
/// </summary>
/// <param name="channels">The channels.</param>
/// <param name="factories">The factories.</param>
- void AddParts(IEnumerable<IChannel> channels, IEnumerable<IChannelFactory> factories);
+ void AddParts(IEnumerable<IChannel> channels);
/// <summary>
/// Gets the channel download path.
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 594b5ca93..25e742e7c 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -62,6 +62,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the channel identifier.
/// </summary>
/// <value>The channel identifier.</value>
+ [IgnoreDataMember]
public string ChannelId { get; set; }
[IgnoreDataMember]
@@ -183,7 +184,7 @@ namespace MediaBrowser.Controller.Entities
{
// Local trailer, special feature, theme video, etc.
// An item that belongs to another item but is not part of the Parent-Child tree
- return !IsFolder && Parent == null && LocationType == LocationType.FileSystem;
+ return !IsFolder && ParentId == Guid.Empty && LocationType == LocationType.FileSystem;
}
}
@@ -331,25 +332,8 @@ namespace MediaBrowser.Controller.Entities
return Name;
}
- /// <summary>
- /// Returns true if this item should not attempt to fetch metadata
- /// </summary>
- /// <value><c>true</c> if [dont fetch meta]; otherwise, <c>false</c>.</value>
- [Obsolete("Please use IsLocked instead of DontFetchMeta")]
- public bool DontFetchMeta { get; set; }
-
[IgnoreDataMember]
- public bool IsLocked
- {
- get
- {
- return DontFetchMeta;
- }
- set
- {
- DontFetchMeta = value;
- }
- }
+ public bool IsLocked { get; set; }
public bool IsUnidentified { get; set; }
@@ -484,7 +468,6 @@ namespace MediaBrowser.Controller.Entities
public Guid ParentId { get; set; }
- private Folder _parent;
/// <summary>
/// Gets or sets the parent.
/// </summary>
@@ -494,11 +477,6 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- if (_parent != null)
- {
- return _parent;
- }
-
if (ParentId != Guid.Empty)
{
return LibraryManager.GetItemById(ParentId) as Folder;
@@ -506,12 +484,14 @@ namespace MediaBrowser.Controller.Entities
return null;
}
- set { _parent = value; }
+ set
+ {
+
+ }
}
public void SetParent(Folder parent)
{
- Parent = parent;
ParentId = parent == null ? Guid.Empty : parent.Id;
}
@@ -558,6 +538,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the end date.
/// </summary>
/// <value>The end date.</value>
+ [IgnoreDataMember]
public DateTime? EndDate { get; set; }
/// <summary>
@@ -582,6 +563,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the custom rating.
/// </summary>
/// <value>The custom rating.</value>
+ [IgnoreDataMember]
public string CustomRating { get; set; }
/// <summary>
@@ -591,12 +573,6 @@ namespace MediaBrowser.Controller.Entities
public string Overview { get; set; }
/// <summary>
- /// Gets or sets the people.
- /// </summary>
- /// <value>The people.</value>
- public List<PersonInfo> People { get; set; }
-
- /// <summary>
/// Gets or sets the studios.
/// </summary>
/// <value>The studios.</value>
@@ -618,6 +594,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the community rating.
/// </summary>
/// <value>The community rating.</value>
+ [IgnoreDataMember]
public float? CommunityRating { get; set; }
/// <summary>
@@ -643,6 +620,7 @@ namespace MediaBrowser.Controller.Entities
/// This could be episode number, album track number, etc.
/// </summary>
/// <value>The index number.</value>
+ [IgnoreDataMember]
public int? IndexNumber { get; set; }
/// <summary>
@@ -705,7 +683,7 @@ namespace MediaBrowser.Controller.Entities
{
var files = fileSystemChildren.OfType<DirectoryInfo>()
.Where(i => string.Equals(i.Name, ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
- .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
+ .SelectMany(i => directoryService.GetFiles(i.FullName))
.ToList();
// Support plex/xbmc convention
@@ -741,7 +719,7 @@ namespace MediaBrowser.Controller.Entities
{
var files = fileSystemChildren.OfType<DirectoryInfo>()
.Where(i => string.Equals(i.Name, ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
- .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly));
+ .SelectMany(i => directoryService.GetFiles(i.FullName));
return LibraryManager.ResolvePaths(files, directoryService, null)
.OfType<Video>()
@@ -765,7 +743,7 @@ namespace MediaBrowser.Controller.Entities
public Task RefreshMetadata(CancellationToken cancellationToken)
{
- return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService()), cancellationToken);
+ return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem)), cancellationToken);
}
/// <summary>
@@ -1114,7 +1092,7 @@ namespace MediaBrowser.Controller.Entities
// Could not determine the integer value
if (!value.HasValue)
{
- return true;
+ return !GetBlockUnratedValue(user.Policy);
}
return value.Value <= maxAllowedRating.Value;
@@ -1418,7 +1396,7 @@ namespace MediaBrowser.Controller.Entities
/// <returns>Task.</returns>
public virtual Task ChangedExternally()
{
- ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions());
+ ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions(FileSystem));
return Task.FromResult(true);
}
@@ -1635,7 +1613,7 @@ namespace MediaBrowser.Controller.Entities
var newImagePaths = images.Select(i => i.FullName).ToList();
var deleted = existingImages
- .Where(i => !newImagePaths.Contains(i.Path, StringComparer.OrdinalIgnoreCase) && !File.Exists(i.Path))
+ .Where(i => !newImagePaths.Contains(i.Path, StringComparer.OrdinalIgnoreCase) && !FileSystem.FileExists(i.Path))
.ToList();
ImageInfos = ImageInfos.Except(deleted).ToList();
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index c3ac77328..4cdc4657e 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -48,7 +48,7 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public virtual bool IsPreSorted
{
- get { return ConfigurationManager.Configuration.EnableWindowsShortcuts; }
+ get { return false; }
}
/// <summary>
@@ -120,7 +120,7 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
protected virtual bool SupportsShortcutChildren
{
- get { return false; }
+ get { return ConfigurationManager.Configuration.EnableWindowsShortcuts; }
}
/// <summary>
@@ -371,7 +371,7 @@ namespace MediaBrowser.Controller.Entities
public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken)
{
- return ValidateChildren(progress, cancellationToken, new MetadataRefreshOptions(new DirectoryService()));
+ return ValidateChildren(progress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(FileSystem)));
}
/// <summary>
@@ -474,7 +474,7 @@ namespace MediaBrowser.Controller.Entities
currentChild.DateModified = child.DateModified;
}
- currentChild.IsOffline = false;
+ await UpdateIsOffline(currentChild, false).ConfigureAwait(false);
validChildren.Add(currentChild);
}
else
@@ -509,12 +509,12 @@ namespace MediaBrowser.Controller.Entities
else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path))
{
- item.IsOffline = true;
+ await UpdateIsOffline(item, true).ConfigureAwait(false);
validChildren.Add(item);
}
else
{
- item.IsOffline = false;
+ await UpdateIsOffline(item, false).ConfigureAwait(false);
actualRemovals.Add(item);
}
}
@@ -569,6 +569,17 @@ namespace MediaBrowser.Controller.Entities
progress.Report(100);
}
+ private Task UpdateIsOffline(BaseItem item, bool newValue)
+ {
+ if (item.IsOffline != newValue)
+ {
+ item.IsOffline = newValue;
+ return item.UpdateToRepository(ItemUpdateType.None, CancellationToken.None);
+ }
+
+ return Task.FromResult(true);
+ }
+
private async Task RefreshMetadataRecursive(MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken)
{
var children = ActualChildren.ToList();
@@ -693,7 +704,7 @@ namespace MediaBrowser.Controller.Entities
/// <returns><c>true</c> if the specified path is offline; otherwise, <c>false</c>.</returns>
private bool IsPathOffline(string path)
{
- if (File.Exists(path))
+ if (FileSystem.FileExists(path))
{
return false;
}
@@ -703,7 +714,7 @@ namespace MediaBrowser.Controller.Entities
// Depending on whether the path is local or unc, it may return either null or '\' at the top
while (!string.IsNullOrEmpty(path) && path.Length > 1)
{
- if (Directory.Exists(path))
+ if (FileSystem.DirectoryExists(path))
{
return false;
}
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index 0af4972f7..bde4d0f45 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -98,7 +98,9 @@ namespace MediaBrowser.Controller.Entities
public bool? IsCurrentSchema { get; set; }
public bool? HasDeadParentId { get; set; }
-
+ public bool? IsOffline { get; set; }
+ public LocationType? LocationType { get; set; }
+
public InternalItemsQuery()
{
Tags = new string[] { };
diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs
index 71e3d1ce0..bf0f7a2a8 100644
--- a/MediaBrowser.Controller/Entities/User.cs
+++ b/MediaBrowser.Controller/Entities/User.cs
@@ -177,24 +177,24 @@ namespace MediaBrowser.Controller.Entities
var oldConfigurationDirectory = ConfigurationDirectoryPath;
// Exceptions will be thrown if these paths already exist
- if (Directory.Exists(newConfigDirectory))
+ if (FileSystem.DirectoryExists(newConfigDirectory))
{
FileSystem.DeleteDirectory(newConfigDirectory, true);
}
- if (Directory.Exists(oldConfigurationDirectory))
+ if (FileSystem.DirectoryExists(oldConfigurationDirectory))
{
- Directory.Move(oldConfigurationDirectory, newConfigDirectory);
+ FileSystem.MoveDirectory(oldConfigurationDirectory, newConfigDirectory);
}
else
{
- Directory.CreateDirectory(newConfigDirectory);
+ FileSystem.CreateDirectory(newConfigDirectory);
}
}
Name = newName;
- return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService())
+ return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem))
{
ReplaceAllMetadata = true,
ImageRefreshMode = ImageRefreshMode.FullRefresh,
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 488e54cc3..f4577435f 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -82,7 +82,27 @@ namespace MediaBrowser.Controller.Entities
{
CollectionType.Books,
CollectionType.HomeVideos,
- CollectionType.Photos
+ CollectionType.Photos,
+ CollectionType.Playlists,
+ CollectionType.BoxSets
+ };
+
+ var collectionFolder = folder as ICollectionFolder;
+
+ if (collectionFolder == null)
+ {
+ return false;
+ }
+
+ return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
+ }
+
+ public static bool IsUserSpecific(Folder folder)
+ {
+ var standaloneTypes = new List<string>
+ {
+ CollectionType.Playlists,
+ CollectionType.BoxSets
};
var collectionFolder = folder as ICollectionFolder;
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index cee5dadd2..e05b838d0 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -577,19 +577,9 @@ namespace MediaBrowser.Controller.Entities
private async Task<QueryResult<BaseItem>> GetBoxsetView(Folder parent, User user, InternalItemsQuery query)
{
- return GetResult(GetMediaFolders(user).SelectMany(i =>
- {
- var hasCollectionType = i as ICollectionFolder;
- Func<BaseItem, bool> filter = b => b is BoxSet;
-
- if (hasCollectionType != null && string.Equals(hasCollectionType.CollectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
- {
- return i.GetChildren(user, true).Where(filter);
- }
-
- return i.GetRecursiveChildren(user, filter);
+ var collections = _collectionManager.GetCollections(user);
- }), parent, query);
+ return GetResult(collections, parent, query);
}
private async Task<QueryResult<BaseItem>> GetPhotosView(Folder queryParent, User user, InternalItemsQuery query)
@@ -1041,12 +1031,12 @@ namespace MediaBrowser.Controller.Entities
return false;
}
- if (request.IsUnidentified.HasValue)
+ if (request.IsYearMismatched.HasValue)
{
return false;
}
- if (request.IsYearMismatched.HasValue)
+ if (request.IsUnidentified.HasValue)
{
return false;
}
@@ -1418,15 +1408,6 @@ namespace MediaBrowser.Controller.Entities
}
}
- if (query.IsUnidentified.HasValue)
- {
- var val = query.IsUnidentified.Value;
- if (item.IsUnidentified != val)
- {
- return false;
- }
- }
-
if (query.IsLocked.HasValue)
{
var val = query.IsLocked.Value;
@@ -1448,6 +1429,15 @@ namespace MediaBrowser.Controller.Entities
}
}
+ if (query.IsUnidentified.HasValue)
+ {
+ var val = query.IsUnidentified.Value;
+ if (item.IsUnidentified != val)
+ {
+ return false;
+ }
+ }
+
if (query.HasImdbId.HasValue)
{
var filterValue = query.HasImdbId.Value;
@@ -1808,6 +1798,13 @@ namespace MediaBrowser.Controller.Entities
private IEnumerable<Folder> GetMediaFolders(User user)
{
+ if (user == null)
+ {
+ return _libraryManager.RootFolder
+ .Children
+ .OfType<Folder>()
+ .Where(i => !UserView.IsExcludedFromGrouping(i));
+ }
return user.RootFolder
.GetChildren(user, true, true)
.OfType<Folder>()
@@ -1816,6 +1813,16 @@ namespace MediaBrowser.Controller.Entities
private IEnumerable<Folder> GetMediaFolders(User user, IEnumerable<string> viewTypes)
{
+ if (user == null)
+ {
+ return GetMediaFolders(null)
+ .Where(i =>
+ {
+ var folder = i as ICollectionFolder;
+
+ return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
+ });
+ }
return GetMediaFolders(user)
.Where(i =>
{
@@ -1839,9 +1846,19 @@ namespace MediaBrowser.Controller.Entities
{
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);
}
@@ -1849,9 +1866,19 @@ namespace MediaBrowser.Controller.Entities
{
if (parent == null || parent is UserView)
{
+ if (user == null)
+ {
+ return GetMediaFolders(null, viewTypes).SelectMany(i => i.GetRecursiveChildren(filter));
+ }
+
return GetMediaFolders(user, viewTypes).SelectMany(i => i.GetRecursiveChildren(user, filter));
}
+ if (user == null)
+ {
+ return parent.GetRecursiveChildren(filter);
+ }
+
return parent.GetRecursiveChildren(user, filter);
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
index 2179c5ecd..1be04bb7c 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
@@ -20,12 +20,16 @@ namespace MediaBrowser.Controller.LiveTv
public string EpisodeTitle { get; set; }
public bool IsSeries { get; set; }
public string SeriesTimerId { get; set; }
+ [IgnoreDataMember]
public DateTime StartDate { get; set; }
public RecordingStatus Status { get; set; }
+ [IgnoreDataMember]
public bool IsSports { get; set; }
public bool IsNews { get; set; }
+ [IgnoreDataMember]
public bool IsKids { get; set; }
public bool IsRepeat { get; set; }
+ [IgnoreDataMember]
public bool IsMovie { get; set; }
public bool? IsHD { get; set; }
public bool IsLive { get; set; }
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
index 12052905f..0f7d0a6ce 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
@@ -56,6 +56,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <summary>
/// The start date of the program, in UTC.
/// </summary>
+ [IgnoreDataMember]
public DateTime StartDate { get; set; }
/// <summary>
@@ -110,12 +111,14 @@ namespace MediaBrowser.Controller.LiveTv
/// Gets or sets a value indicating whether this instance is movie.
/// </summary>
/// <value><c>true</c> if this instance is movie; otherwise, <c>false</c>.</value>
+ [IgnoreDataMember]
public bool IsMovie { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is sports.
/// </summary>
/// <value><c>true</c> if this instance is sports; otherwise, <c>false</c>.</value>
+ [IgnoreDataMember]
public bool IsSports { get; set; }
/// <summary>
@@ -140,6 +143,7 @@ namespace MediaBrowser.Controller.LiveTv
/// Gets or sets a value indicating whether this instance is kids.
/// </summary>
/// <value><c>true</c> if this instance is kids; otherwise, <c>false</c>.</value>
+ [IgnoreDataMember]
public bool IsKids { get; set; }
/// <summary>
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
index 960f8054a..a26d8b402 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
@@ -20,12 +20,16 @@ namespace MediaBrowser.Controller.LiveTv
public string EpisodeTitle { get; set; }
public bool IsSeries { get; set; }
public string SeriesTimerId { get; set; }
+ [IgnoreDataMember]
public DateTime StartDate { get; set; }
public RecordingStatus Status { get; set; }
+ [IgnoreDataMember]
public bool IsSports { get; set; }
public bool IsNews { get; set; }
+ [IgnoreDataMember]
public bool IsKids { get; set; }
public bool IsRepeat { get; set; }
+ [IgnoreDataMember]
public bool IsMovie { get; set; }
public bool? IsHD { get; set; }
public bool IsLive { get; set; }
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 24309734f..ea6e98ea6 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -11,10 +11,10 @@
<AssemblyName>MediaBrowser.Controller</AssemblyName>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
- <ProductVersion>10.0.0</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<RestorePackages>true</RestorePackages>
+ <ReleaseVersion>
+ </ReleaseVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -24,7 +24,6 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@@ -33,7 +32,6 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
@@ -45,16 +43,11 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Interfaces.IO">
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
</Reference>
- <Reference Include="MoreLinq, Version=1.1.17511.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\morelinq.1.1.0\lib\net35\MoreLinq.dll</HintPath>
- </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
@@ -66,6 +59,9 @@
<Reference Include="ServiceStack.Interfaces">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
@@ -81,7 +77,6 @@
<Compile Include="Channels\ChannelParentalRating.cs" />
<Compile Include="Channels\ChannelSearchInfo.cs" />
<Compile Include="Channels\IChannel.cs" />
- <Compile Include="Channels\IChannelFactory.cs" />
<Compile Include="Channels\IChannelManager.cs" />
<Compile Include="Channels\IChannelItem.cs" />
<Compile Include="Channels\ChannelAudioItem.cs" />
@@ -418,8 +413,6 @@
<Compile Include="Sync\ISyncRepository.cs" />
<Compile Include="Sync\SyncedFileInfo.cs" />
<Compile Include="Sync\SyncedItemProgress.cs" />
- <Compile Include="Themes\IAppThemeManager.cs" />
- <Compile Include="Themes\InternalThemeImage.cs" />
<Compile Include="TV\ITVSeriesManager.cs" />
</ItemGroup>
<ItemGroup>
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index 23285b612..427af6f6d 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -25,6 +25,13 @@ namespace MediaBrowser.Controller.MediaEncoding
string Version { get; }
/// <summary>
+ /// Supportses the decoder.
+ /// </summary>
+ /// <param name="decoder">The decoder.</param>
+ /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
+ bool SupportsDecoder(string decoder);
+
+ /// <summary>
/// Extracts the audio image.
/// </summary>
/// <param name="path">The path.</param>
diff --git a/MediaBrowser.Controller/Net/IHttpServer.cs b/MediaBrowser.Controller/Net/IHttpServer.cs
index 37142af19..91da5fab2 100644
--- a/MediaBrowser.Controller/Net/IHttpServer.cs
+++ b/MediaBrowser.Controller/Net/IHttpServer.cs
@@ -53,5 +53,10 @@ namespace MediaBrowser.Controller.Net
/// Inits this instance.
/// </summary>
void Init(IEnumerable<IRestfulService> services);
+
+ /// <summary>
+ /// If set, all requests will respond with this message
+ /// </summary>
+ string GlobalResponse { get; set; }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index a4b9bf120..8fc0aedd3 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -169,6 +169,13 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="query">The query.</param>
/// <returns>List&lt;System.String&gt;.</returns>
List<string> GetPeopleNames(InternalPeopleQuery query);
+
+ /// <summary>
+ /// Gets the item ids with path.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <returns>QueryResult&lt;Tuple&lt;Guid, System.String&gt;&gt;.</returns>
+ QueryResult<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query);
}
}
diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs
index 79ffb0d01..d320409f4 100644
--- a/MediaBrowser.Controller/Providers/DirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/DirectoryService.cs
@@ -4,23 +4,26 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Controller.Providers
{
public class DirectoryService : IDirectoryService
{
private readonly ILogger _logger;
+ private readonly IFileSystem _fileSystem;
private readonly ConcurrentDictionary<string, Dictionary<string,FileSystemInfo>> _cache =
new ConcurrentDictionary<string, Dictionary<string, FileSystemInfo>>(StringComparer.OrdinalIgnoreCase);
- public DirectoryService(ILogger logger)
+ public DirectoryService(ILogger logger, IFileSystem fileSystem)
{
_logger = logger;
+ _fileSystem = fileSystem;
}
- public DirectoryService()
- : this(new NullLogger())
+ public DirectoryService(IFileSystem fileSystem)
+ : this(new NullLogger(), fileSystem)
{
}
@@ -59,8 +62,7 @@ namespace MediaBrowser.Controller.Providers
try
{
// using EnumerateFileSystemInfos doesn't handle reparse points (symlinks)
- var list = new DirectoryInfo(path).EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
- .Concat<FileSystemInfo>(new DirectoryInfo(path).EnumerateFiles("*", SearchOption.TopDirectoryOnly));
+ var list = _fileSystem.GetFileSystemEntries(path);
// Seeing dupes on some users file system for some reason
foreach (var item in list)
diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
index dbb7fbfcd..097c613cb 100644
--- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
+++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
@@ -1,4 +1,5 @@
using System.Linq;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Controller.Providers
{
@@ -15,8 +16,8 @@ namespace MediaBrowser.Controller.Providers
public bool ForceSave { get; set; }
- public MetadataRefreshOptions()
- : this(new DirectoryService())
+ public MetadataRefreshOptions(IFileSystem fileSystem)
+ : this(new DirectoryService(fileSystem))
{
}
diff --git a/MediaBrowser.Controller/Providers/MetadataStatus.cs b/MediaBrowser.Controller/Providers/MetadataStatus.cs
index 283b9edbc..f395dabf1 100644
--- a/MediaBrowser.Controller/Providers/MetadataStatus.cs
+++ b/MediaBrowser.Controller/Providers/MetadataStatus.cs
@@ -78,9 +78,9 @@ namespace MediaBrowser.Controller.Providers
public bool IsDirty { get; private set; }
- public void SetDateLastMetadataRefresh(DateTime date)
+ public void SetDateLastMetadataRefresh(DateTime? date)
{
- if (date != (DateLastMetadataRefresh ?? DateTime.MinValue))
+ if (date != DateLastMetadataRefresh)
{
IsDirty = true;
}
@@ -88,9 +88,9 @@ namespace MediaBrowser.Controller.Providers
DateLastMetadataRefresh = date;
}
- public void SetDateLastImagesRefresh(DateTime date)
+ public void SetDateLastImagesRefresh(DateTime? date)
{
- if (date != (DateLastImagesRefresh ?? DateTime.MinValue))
+ if (date != DateLastImagesRefresh)
{
IsDirty = true;
}
diff --git a/MediaBrowser.Controller/Themes/IAppThemeManager.cs b/MediaBrowser.Controller/Themes/IAppThemeManager.cs
deleted file mode 100644
index 1a7c2aaab..000000000
--- a/MediaBrowser.Controller/Themes/IAppThemeManager.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using MediaBrowser.Model.Themes;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Controller.Themes
-{
- public interface IAppThemeManager
- {
- /// <summary>
- /// Gets the themes.
- /// </summary>
- /// <param name="applicationName">Name of the application.</param>
- /// <returns>IEnumerable{AppThemeInfo}.</returns>
- IEnumerable<AppThemeInfo> GetThemes(string applicationName);
-
- /// <summary>
- /// Gets the theme.
- /// </summary>
- /// <param name="applicationName">Name of the application.</param>
- /// <param name="name">The name.</param>
- /// <returns>AppTheme.</returns>
- AppTheme GetTheme(string applicationName, string name);
-
- /// <summary>
- /// Saves the theme.
- /// </summary>
- /// <param name="theme">The theme.</param>
- void SaveTheme(AppTheme theme);
-
- /// <summary>
- /// Gets the image image information.
- /// </summary>
- /// <param name="applicationName">Name of the application.</param>
- /// <param name="themeName">Name of the theme.</param>
- /// <param name="imageName">Name of the image.</param>
- /// <returns>InternalThemeImage.</returns>
- InternalThemeImage GetImageImageInfo(string applicationName, string themeName, string imageName);
- }
-}
diff --git a/MediaBrowser.Controller/Themes/InternalThemeImage.cs b/MediaBrowser.Controller/Themes/InternalThemeImage.cs
deleted file mode 100644
index 2b676c25b..000000000
--- a/MediaBrowser.Controller/Themes/InternalThemeImage.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using System;
-
-namespace MediaBrowser.Controller.Themes
-{
- public class InternalThemeImage
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the cache tag.
- /// </summary>
- /// <value>The cache tag.</value>
- public string CacheTag { get; set; }
-
- /// <summary>
- /// Gets or sets the path.
- /// </summary>
- /// <value>The path.</value>
- public string Path { get; set; }
-
- /// <summary>
- /// Gets or sets the date modified.
- /// </summary>
- /// <value>The date modified.</value>
- public DateTime DateModified { get; set; }
- }
-}
diff --git a/MediaBrowser.Controller/packages.config b/MediaBrowser.Controller/packages.config
index 8846b5a06..c320ed9d9 100644
--- a/MediaBrowser.Controller/packages.config
+++ b/MediaBrowser.Controller/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
- <package id="morelinq" version="1.1.0" targetFramework="net45" />
+ <package id="morelinq" version="1.1.1" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs
index f26ceff90..315313c04 100644
--- a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs
+++ b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs
@@ -18,325 +18,325 @@ using System.Threading.Tasks;
namespace MediaBrowser.Dlna.Channels
{
- public class DlnaChannelFactory : IChannelFactory, IDisposable
- {
- private readonly IServerConfigurationManager _config;
- private readonly ILogger _logger;
- private readonly IHttpClient _httpClient;
-
- private readonly IDeviceDiscovery _deviceDiscovery;
-
- private readonly SemaphoreSlim _syncLock = new SemaphoreSlim(1, 1);
- private List<Device> _servers = new List<Device>();
-
- public static DlnaChannelFactory Instance;
-
- private Func<List<string>> _localServersLookup;
-
- public DlnaChannelFactory(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger, IDeviceDiscovery deviceDiscovery)
- {
- _config = config;
- _httpClient = httpClient;
- _logger = logger;
- _deviceDiscovery = deviceDiscovery;
- Instance = this;
- }
-
- internal void Start(Func<List<string>> localServersLookup)
- {
- _localServersLookup = localServersLookup;
-
- //deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered;
- _deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft;
- }
-
- async void deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)
- {
- string usn;
- if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty;
-
- string nt;
- if (!e.Headers.TryGetValue("NT", out nt)) nt = string.Empty;
-
- string location;
- if (!e.Headers.TryGetValue("Location", out location)) location = string.Empty;
-
- if (!IsValid(nt, usn))
- {
- return;
- }
-
- if (_localServersLookup != null)
- {
- if (_localServersLookup().Any(i => usn.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1))
- {
- // Don't add the local Dlna server to this
- return;
- }
- }
-
- if (GetExistingServers(usn).Any())
- {
- return;
- }
-
- await _syncLock.WaitAsync().ConfigureAwait(false);
-
- try
- {
- if (GetExistingServers(usn).Any())
- {
- return;
- }
-
- var device = await Device.CreateuPnpDeviceAsync(new Uri(location), _httpClient, _config, _logger)
- .ConfigureAwait(false);
-
- if (!_servers.Any(i => string.Equals(i.Properties.UUID, device.Properties.UUID, StringComparison.OrdinalIgnoreCase)))
- {
- _servers.Add(device);
- }
- }
- catch (Exception ex)
- {
-
- }
- finally
- {
- _syncLock.Release();
- }
- }
-
- async void deviceDiscovery_DeviceLeft(object sender, SsdpMessageEventArgs e)
- {
- string usn;
- if (!e.Headers.TryGetValue("USN", out usn)) usn = String.Empty;
-
- string nt;
- if (!e.Headers.TryGetValue("NT", out nt)) nt = String.Empty;
-
- if (!IsValid(nt, usn))
- {
- return;
- }
-
- if (!GetExistingServers(usn).Any())
- {
- return;
- }
-
- await _syncLock.WaitAsync().ConfigureAwait(false);
-
- try
- {
- var list = _servers.ToList();
-
- foreach (var device in GetExistingServers(usn).ToList())
- {
- list.Remove(device);
- }
-
- _servers = list;
- }
- finally
- {
- _syncLock.Release();
- }
- }
-
- private bool IsValid(string nt, string usn)
- {
- // It has to report that it's a media renderer
- if (usn.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 &&
- nt.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 &&
- usn.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1 &&
- nt.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1)
- {
- return false;
- }
-
- return true;
- }
-
- private IEnumerable<Device> GetExistingServers(string usn)
- {
- return _servers
- .Where(i => usn.IndexOf(i.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1);
- }
-
- public IEnumerable<IChannel> GetChannels()
- {
- //if (_servers.Count > 0)
- //{
- // var service = _servers[0].Properties.Services
- // .FirstOrDefault(i => string.Equals(i.ServiceType, "urn:schemas-upnp-org:service:ContentDirectory:1", StringComparison.OrdinalIgnoreCase));
-
- // var controlUrl = service == null ? null : (_servers[0].Properties.BaseUrl.TrimEnd('/') + "/" + service.ControlUrl.TrimStart('/'));
-
- // if (!string.IsNullOrEmpty(controlUrl))
- // {
- // return new List<IChannel>
- // {
- // new ServerChannel(_servers.ToList(), _httpClient, _logger, controlUrl)
- // };
- // }
- //}
-
- return new List<IChannel>();
- }
-
- public void Dispose()
- {
- if (_deviceDiscovery != null)
- {
- _deviceDiscovery.DeviceDiscovered -= deviceDiscovery_DeviceDiscovered;
- _deviceDiscovery.DeviceLeft -= deviceDiscovery_DeviceLeft;
- }
- }
- }
-
- public class ServerChannel : IChannel, IFactoryChannel
- {
- private readonly IHttpClient _httpClient;
- private readonly ILogger _logger;
- public string ControlUrl { get; set; }
- public List<Device> Servers { get; set; }
-
- public ServerChannel(IHttpClient httpClient, ILogger logger)
- {
- _httpClient = httpClient;
- _logger = logger;
- Servers = new List<Device>();
- }
-
- public string Name
- {
- get { return "Devices"; }
- }
-
- public string Description
- {
- get { return string.Empty; }
- }
-
- public string DataVersion
- {
- get { return DateTime.UtcNow.Ticks.ToString(); }
- }
-
- public string HomePageUrl
- {
- get { return string.Empty; }
- }
-
- public ChannelParentalRating ParentalRating
- {
- get { return ChannelParentalRating.GeneralAudience; }
- }
-
- public InternalChannelFeatures GetChannelFeatures()
- {
- return new InternalChannelFeatures
- {
- ContentTypes = new List<ChannelMediaContentType>
- {
- ChannelMediaContentType.Song,
- ChannelMediaContentType.Clip
- },
-
- MediaTypes = new List<ChannelMediaType>
- {
- ChannelMediaType.Audio,
- ChannelMediaType.Video,
- ChannelMediaType.Photo
- }
- };
- }
-
- public bool IsEnabledFor(string userId)
- {
- return true;
- }
-
- public async Task<ChannelItemResult> GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken)
- {
- IEnumerable<ChannelItemInfo> items;
-
- if (string.IsNullOrWhiteSpace(query.FolderId))
- {
- items = Servers.Select(i => new ChannelItemInfo
- {
- FolderType = ChannelFolderType.Container,
- Id = GetServerId(i),
- Name = i.Properties.Name,
- Overview = i.Properties.ModelDescription,
- Type = ChannelItemType.Folder
- });
- }
- else
- {
- var idParts = query.FolderId.Split('|');
- var folderId = idParts.Length == 2 ? idParts[1] : null;
-
- var result = await new ContentDirectoryBrowser(_httpClient, _logger).Browse(new ContentDirectoryBrowseRequest
- {
- Limit = query.Limit,
- StartIndex = query.StartIndex,
- ParentId = folderId,
- ContentDirectoryUrl = ControlUrl
-
- }, cancellationToken).ConfigureAwait(false);
-
- items = result.Items.ToList();
- }
-
- var list = items.ToList();
- var count = list.Count;
-
- list = ApplyPaging(list, query).ToList();
-
- return new ChannelItemResult
- {
- Items = list,
- TotalRecordCount = count
- };
- }
-
- private string GetServerId(Device device)
- {
- return device.Properties.UUID.GetMD5().ToString("N");
- }
-
- private IEnumerable<T> ApplyPaging<T>(IEnumerable<T> items, InternalChannelItemQuery query)
- {
- if (query.StartIndex.HasValue)
- {
- items = items.Skip(query.StartIndex.Value);
- }
-
- if (query.Limit.HasValue)
- {
- items = items.Take(query.Limit.Value);
- }
-
- return items;
- }
-
- public Task<DynamicImageResponse> GetChannelImage(ImageType type, CancellationToken cancellationToken)
- {
- // TODO: Implement
- return Task.FromResult(new DynamicImageResponse
- {
- HasImage = false
- });
- }
-
- public IEnumerable<ImageType> GetSupportedChannelImages()
- {
- return new List<ImageType>
- {
- ImageType.Primary
- };
- }
- }
+ //public class DlnaChannelFactory : IChannelFactory, IDisposable
+ //{
+ // private readonly IServerConfigurationManager _config;
+ // private readonly ILogger _logger;
+ // private readonly IHttpClient _httpClient;
+
+ // private readonly IDeviceDiscovery _deviceDiscovery;
+
+ // private readonly SemaphoreSlim _syncLock = new SemaphoreSlim(1, 1);
+ // private List<Device> _servers = new List<Device>();
+
+ // public static DlnaChannelFactory Instance;
+
+ // private Func<List<string>> _localServersLookup;
+
+ // public DlnaChannelFactory(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger, IDeviceDiscovery deviceDiscovery)
+ // {
+ // _config = config;
+ // _httpClient = httpClient;
+ // _logger = logger;
+ // _deviceDiscovery = deviceDiscovery;
+ // Instance = this;
+ // }
+
+ // internal void Start(Func<List<string>> localServersLookup)
+ // {
+ // _localServersLookup = localServersLookup;
+
+ // //deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered;
+ // _deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft;
+ // }
+
+ // async void deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)
+ // {
+ // string usn;
+ // if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty;
+
+ // string nt;
+ // if (!e.Headers.TryGetValue("NT", out nt)) nt = string.Empty;
+
+ // string location;
+ // if (!e.Headers.TryGetValue("Location", out location)) location = string.Empty;
+
+ // if (!IsValid(nt, usn))
+ // {
+ // return;
+ // }
+
+ // if (_localServersLookup != null)
+ // {
+ // if (_localServersLookup().Any(i => usn.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1))
+ // {
+ // // Don't add the local Dlna server to this
+ // return;
+ // }
+ // }
+
+ // if (GetExistingServers(usn).Any())
+ // {
+ // return;
+ // }
+
+ // await _syncLock.WaitAsync().ConfigureAwait(false);
+
+ // try
+ // {
+ // if (GetExistingServers(usn).Any())
+ // {
+ // return;
+ // }
+
+ // var device = await Device.CreateuPnpDeviceAsync(new Uri(location), _httpClient, _config, _logger)
+ // .ConfigureAwait(false);
+
+ // if (!_servers.Any(i => string.Equals(i.Properties.UUID, device.Properties.UUID, StringComparison.OrdinalIgnoreCase)))
+ // {
+ // _servers.Add(device);
+ // }
+ // }
+ // catch (Exception ex)
+ // {
+
+ // }
+ // finally
+ // {
+ // _syncLock.Release();
+ // }
+ // }
+
+ // async void deviceDiscovery_DeviceLeft(object sender, SsdpMessageEventArgs e)
+ // {
+ // string usn;
+ // if (!e.Headers.TryGetValue("USN", out usn)) usn = String.Empty;
+
+ // string nt;
+ // if (!e.Headers.TryGetValue("NT", out nt)) nt = String.Empty;
+
+ // if (!IsValid(nt, usn))
+ // {
+ // return;
+ // }
+
+ // if (!GetExistingServers(usn).Any())
+ // {
+ // return;
+ // }
+
+ // await _syncLock.WaitAsync().ConfigureAwait(false);
+
+ // try
+ // {
+ // var list = _servers.ToList();
+
+ // foreach (var device in GetExistingServers(usn).ToList())
+ // {
+ // list.Remove(device);
+ // }
+
+ // _servers = list;
+ // }
+ // finally
+ // {
+ // _syncLock.Release();
+ // }
+ // }
+
+ // private bool IsValid(string nt, string usn)
+ // {
+ // // It has to report that it's a media renderer
+ // if (usn.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 &&
+ // nt.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 &&
+ // usn.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1 &&
+ // nt.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1)
+ // {
+ // return false;
+ // }
+
+ // return true;
+ // }
+
+ // private IEnumerable<Device> GetExistingServers(string usn)
+ // {
+ // return _servers
+ // .Where(i => usn.IndexOf(i.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1);
+ // }
+
+ // public IEnumerable<IChannel> GetChannels()
+ // {
+ // //if (_servers.Count > 0)
+ // //{
+ // // var service = _servers[0].Properties.Services
+ // // .FirstOrDefault(i => string.Equals(i.ServiceType, "urn:schemas-upnp-org:service:ContentDirectory:1", StringComparison.OrdinalIgnoreCase));
+
+ // // var controlUrl = service == null ? null : (_servers[0].Properties.BaseUrl.TrimEnd('/') + "/" + service.ControlUrl.TrimStart('/'));
+
+ // // if (!string.IsNullOrEmpty(controlUrl))
+ // // {
+ // // return new List<IChannel>
+ // // {
+ // // new ServerChannel(_servers.ToList(), _httpClient, _logger, controlUrl)
+ // // };
+ // // }
+ // //}
+
+ // return new List<IChannel>();
+ // }
+
+ // public void Dispose()
+ // {
+ // if (_deviceDiscovery != null)
+ // {
+ // _deviceDiscovery.DeviceDiscovered -= deviceDiscovery_DeviceDiscovered;
+ // _deviceDiscovery.DeviceLeft -= deviceDiscovery_DeviceLeft;
+ // }
+ // }
+ //}
+
+ //public class ServerChannel : IChannel, IFactoryChannel
+ //{
+ // private readonly IHttpClient _httpClient;
+ // private readonly ILogger _logger;
+ // public string ControlUrl { get; set; }
+ // public List<Device> Servers { get; set; }
+
+ // public ServerChannel(IHttpClient httpClient, ILogger logger)
+ // {
+ // _httpClient = httpClient;
+ // _logger = logger;
+ // Servers = new List<Device>();
+ // }
+
+ // public string Name
+ // {
+ // get { return "Devices"; }
+ // }
+
+ // public string Description
+ // {
+ // get { return string.Empty; }
+ // }
+
+ // public string DataVersion
+ // {
+ // get { return DateTime.UtcNow.Ticks.ToString(); }
+ // }
+
+ // public string HomePageUrl
+ // {
+ // get { return string.Empty; }
+ // }
+
+ // public ChannelParentalRating ParentalRating
+ // {
+ // get { return ChannelParentalRating.GeneralAudience; }
+ // }
+
+ // public InternalChannelFeatures GetChannelFeatures()
+ // {
+ // return new InternalChannelFeatures
+ // {
+ // ContentTypes = new List<ChannelMediaContentType>
+ // {
+ // ChannelMediaContentType.Song,
+ // ChannelMediaContentType.Clip
+ // },
+
+ // MediaTypes = new List<ChannelMediaType>
+ // {
+ // ChannelMediaType.Audio,
+ // ChannelMediaType.Video,
+ // ChannelMediaType.Photo
+ // }
+ // };
+ // }
+
+ // public bool IsEnabledFor(string userId)
+ // {
+ // return true;
+ // }
+
+ // public async Task<ChannelItemResult> GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken)
+ // {
+ // IEnumerable<ChannelItemInfo> items;
+
+ // if (string.IsNullOrWhiteSpace(query.FolderId))
+ // {
+ // items = Servers.Select(i => new ChannelItemInfo
+ // {
+ // FolderType = ChannelFolderType.Container,
+ // Id = GetServerId(i),
+ // Name = i.Properties.Name,
+ // Overview = i.Properties.ModelDescription,
+ // Type = ChannelItemType.Folder
+ // });
+ // }
+ // else
+ // {
+ // var idParts = query.FolderId.Split('|');
+ // var folderId = idParts.Length == 2 ? idParts[1] : null;
+
+ // var result = await new ContentDirectoryBrowser(_httpClient, _logger).Browse(new ContentDirectoryBrowseRequest
+ // {
+ // Limit = query.Limit,
+ // StartIndex = query.StartIndex,
+ // ParentId = folderId,
+ // ContentDirectoryUrl = ControlUrl
+
+ // }, cancellationToken).ConfigureAwait(false);
+
+ // items = result.Items.ToList();
+ // }
+
+ // var list = items.ToList();
+ // var count = list.Count;
+
+ // list = ApplyPaging(list, query).ToList();
+
+ // return new ChannelItemResult
+ // {
+ // Items = list,
+ // TotalRecordCount = count
+ // };
+ // }
+
+ // private string GetServerId(Device device)
+ // {
+ // return device.Properties.UUID.GetMD5().ToString("N");
+ // }
+
+ // private IEnumerable<T> ApplyPaging<T>(IEnumerable<T> items, InternalChannelItemQuery query)
+ // {
+ // if (query.StartIndex.HasValue)
+ // {
+ // items = items.Skip(query.StartIndex.Value);
+ // }
+
+ // if (query.Limit.HasValue)
+ // {
+ // items = items.Take(query.Limit.Value);
+ // }
+
+ // return items;
+ // }
+
+ // public Task<DynamicImageResponse> GetChannelImage(ImageType type, CancellationToken cancellationToken)
+ // {
+ // // TODO: Implement
+ // return Task.FromResult(new DynamicImageResponse
+ // {
+ // HasImage = false
+ // });
+ // }
+
+ // public IEnumerable<ImageType> GetSupportedChannelImages()
+ // {
+ // return new List<ImageType>
+ // {
+ // ImageType.Primary
+ // };
+ // }
+ //}
}
diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs
index 95e2aaa77..0fd3cec89 100644
--- a/MediaBrowser.Dlna/DlnaManager.cs
+++ b/MediaBrowser.Dlna/DlnaManager.cs
@@ -279,8 +279,7 @@ namespace MediaBrowser.Dlna
{
try
{
- return new DirectoryInfo(path)
- .EnumerateFiles("*", SearchOption.TopDirectoryOnly)
+ return _fileSystem.GetFiles(path)
.Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase))
.Select(i => ParseProfileXmlFile(i.FullName, type))
.Where(i => i != null)
@@ -342,8 +341,7 @@ namespace MediaBrowser.Dlna
{
try
{
- return new DirectoryInfo(path)
- .EnumerateFiles("*", SearchOption.TopDirectoryOnly)
+ return _fileSystem.GetFiles(path)
.Where(i => string.Equals(i.Extension, ".xml", StringComparison.OrdinalIgnoreCase))
.Select(i => new InternalProfileInfo
{
@@ -385,7 +383,7 @@ namespace MediaBrowser.Dlna
if (!fileInfo.Exists || fileInfo.Length != stream.Length)
{
- Directory.CreateDirectory(systemProfilesPath);
+ _fileSystem.CreateDirectory(systemProfilesPath);
using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
{
@@ -396,7 +394,7 @@ namespace MediaBrowser.Dlna
}
// Not necessary, but just to make it easy to find
- Directory.CreateDirectory(UserProfilesPath);
+ _fileSystem.CreateDirectory(UserProfilesPath);
}
public void DeleteProfile(string id)
diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
index bdb778cab..8c45757e7 100644
--- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
+++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
@@ -81,8 +81,6 @@ namespace MediaBrowser.Dlna.Main
ReloadComponents();
_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
-
- DlnaChannelFactory.Instance.Start(() => _registeredServerIds);
}
void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
diff --git a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
index e6ae84169..a2180439e 100644
--- a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
@@ -21,11 +22,13 @@ namespace MediaBrowser.LocalMetadata.Savers
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private readonly IFileSystem _fileSystem;
- public BoxSetXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager)
+ public BoxSetXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_config = config;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -62,7 +65,7 @@ namespace MediaBrowser.LocalMetadata.Savers
var xmlFilePath = GetSavePath(item);
- XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }, _config);
+ XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }, _config, _fileSystem);
}
/// <summary>
diff --git a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs
index 96d95d40b..284f33de9 100644
--- a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs
@@ -9,6 +9,7 @@ using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
@@ -19,12 +20,14 @@ namespace MediaBrowser.LocalMetadata.Savers
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private IFileSystem _fileSystem;
- public EpisodeXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager)
+ public EpisodeXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_itemRepository = itemRepository;
_config = config;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -143,7 +146,8 @@ namespace MediaBrowser.LocalMetadata.Savers
"DVD_episodenumber",
"DVD_season",
"absolute_number"
- }, _config);
+
+ }, _config, _fileSystem);
}
/// <summary>
diff --git a/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
index ac56f0864..655d41255 100644
--- a/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
@@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
@@ -24,11 +25,13 @@ namespace MediaBrowser.LocalMetadata.Savers
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private readonly IFileSystem _fileSystem;
- public FolderXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager)
+ public FolderXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_config = config;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -76,7 +79,7 @@ namespace MediaBrowser.LocalMetadata.Savers
var xmlFilePath = GetSavePath(item);
- XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }, _config);
+ XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }, _config, _fileSystem);
}
/// <summary>
diff --git a/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs
index 770f1d7f9..c6d21655f 100644
--- a/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs
@@ -6,6 +6,7 @@ using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
@@ -21,11 +22,13 @@ namespace MediaBrowser.LocalMetadata.Savers
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private readonly IFileSystem _fileSystem;
- public GameSystemXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager)
+ public GameSystemXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_config = config;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -69,7 +72,7 @@ namespace MediaBrowser.LocalMetadata.Savers
var xmlFilePath = GetSavePath(item);
- XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }, _config);
+ XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { }, _config, _fileSystem);
}
/// <summary>
diff --git a/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs
index 26c4ff395..fe5d6b27a 100644
--- a/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs
@@ -8,6 +8,7 @@ using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
@@ -26,11 +27,13 @@ namespace MediaBrowser.LocalMetadata.Savers
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private readonly IFileSystem _fileSystem;
- public GameXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager)
+ public GameXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_config = config;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -101,7 +104,7 @@ namespace MediaBrowser.LocalMetadata.Savers
"GameSystem",
"NesBox",
"NesBoxRom"
- }, _config);
+ }, _config, _fileSystem);
}
public string GetSavePath(IHasMetadata item)
diff --git a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs
index a6fba3e9b..46d549a3e 100644
--- a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs
@@ -9,6 +9,7 @@ using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
@@ -20,12 +21,14 @@ namespace MediaBrowser.LocalMetadata.Savers
private readonly IItemRepository _itemRepository;
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private IFileSystem _fileSystem;
- public MovieXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager)
+ public MovieXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_itemRepository = itemRepository;
_config = config;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
public string Name
@@ -122,7 +125,7 @@ namespace MediaBrowser.LocalMetadata.Savers
"Artist",
"Album",
"TmdbCollectionName"
- }, _config);
+ }, _config, _fileSystem);
}
public string GetSavePath(IHasMetadata item)
diff --git a/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs
index 9d943bfa4..d199cb3b8 100644
--- a/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs
@@ -6,6 +6,7 @@ using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
@@ -24,11 +25,13 @@ namespace MediaBrowser.LocalMetadata.Savers
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private readonly IFileSystem _fileSystem;
- public PersonXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager)
+ public PersonXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_config = config;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -75,7 +78,7 @@ namespace MediaBrowser.LocalMetadata.Savers
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
{
"PlaceOfBirth"
- }, _config);
+ }, _config, _fileSystem);
}
/// <summary>
diff --git a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
index 7dfe59b4b..4e047252f 100644
--- a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
@@ -7,6 +7,7 @@ using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
@@ -22,11 +23,13 @@ namespace MediaBrowser.LocalMetadata.Savers
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private readonly IFileSystem _fileSystem;
- public PlaylistXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager)
+ public PlaylistXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_config = config;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -75,7 +78,7 @@ namespace MediaBrowser.LocalMetadata.Savers
"OwnerUserId",
"PlaylistMediaType"
- }, _config);
+ }, _config, _fileSystem);
}
/// <summary>
diff --git a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs
index 44b1cd8d3..8150695e7 100644
--- a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs
@@ -9,6 +9,7 @@ using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
@@ -16,11 +17,13 @@ namespace MediaBrowser.LocalMetadata.Savers
{
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private IFileSystem _fileSystem;
- public SeriesXmlProvider(IServerConfigurationManager config, ILibraryManager libraryManager)
+ public SeriesXmlProvider(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_config = config;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
public string Name
@@ -134,7 +137,7 @@ namespace MediaBrowser.LocalMetadata.Savers
// Deprecated. No longer saving in this field.
"AnimeSeriesIndex"
- }, _config);
+ }, _config, _fileSystem);
}
/// <summary>
diff --git a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
index 091d59469..d90d22be3 100644
--- a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
+++ b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
@@ -14,6 +14,7 @@ using System.Linq;
using System.Security;
using System.Text;
using System.Xml;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.LocalMetadata.Savers
{
@@ -130,9 +131,9 @@ namespace MediaBrowser.LocalMetadata.Savers
/// <param name="xml">The XML.</param>
/// <param name="path">The path.</param>
/// <param name="xmlTagsUsed">The XML tags used.</param>
- public static void Save(StringBuilder xml, string path, List<string> xmlTagsUsed, IServerConfigurationManager config)
+ public static void Save(StringBuilder xml, string path, List<string> xmlTagsUsed, IServerConfigurationManager config, IFileSystem fileSystem)
{
- if (File.Exists(path))
+ if (fileSystem.FileExists(path))
{
var position = xml.ToString().LastIndexOf("</", StringComparison.OrdinalIgnoreCase);
xml.Insert(position, GetCustomTags(path, xmlTagsUsed));
@@ -144,7 +145,7 @@ namespace MediaBrowser.LocalMetadata.Savers
//Add the new node to the document.
xmlDocument.InsertBefore(xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", "yes"), xmlDocument.DocumentElement);
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ fileSystem.CreateDirectory(Path.GetDirectoryName(path));
var wasHidden = false;
diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs
index 17470d206..81f2a75ff 100644
--- a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs
+++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs
@@ -2,26 +2,37 @@
using MediaBrowser.Model.Configuration;
using System.Collections.Generic;
using System.IO;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.MediaEncoding.Configuration
{
public class EncodingConfigurationFactory : IConfigurationFactory
{
+ private readonly IFileSystem _fileSystem;
+
+ public EncodingConfigurationFactory(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
public IEnumerable<ConfigurationStore> GetConfigurations()
{
return new[]
{
- new EncodingConfigurationStore()
+ new EncodingConfigurationStore(_fileSystem)
};
}
}
public class EncodingConfigurationStore : ConfigurationStore, IValidatingConfiguration
{
- public EncodingConfigurationStore()
+ private readonly IFileSystem _fileSystem;
+
+ public EncodingConfigurationStore(IFileSystem fileSystem)
{
ConfigurationType = typeof(EncodingOptions);
Key = "encoding";
+ _fileSystem = fileSystem;
}
public void Validate(object oldConfig, object newConfig)
@@ -35,7 +46,7 @@ namespace MediaBrowser.MediaEncoding.Configuration
&& !string.Equals(oldEncodingConfig.TranscodingTempPath ?? string.Empty, newPath))
{
// Validate
- if (!Directory.Exists(newPath))
+ if (!_fileSystem.DirectoryExists(newPath))
{
throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
}
diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
index 181f147b4..55a3983bb 100644
--- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
@@ -65,7 +65,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
.CreateJob(options, IsVideoEncoder, progress, cancellationToken).ConfigureAwait(false);
encodingJob.OutputFilePath = GetOutputFilePath(encodingJob);
- Directory.CreateDirectory(Path.GetDirectoryName(encodingJob.OutputFilePath));
+ FileSystem.CreateDirectory(Path.GetDirectoryName(encodingJob.OutputFilePath));
encodingJob.ReadInputAtNativeFramerate = options.ReadInputAtNativeFramerate;
@@ -112,7 +112,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
Logger.Info(commandLineLogMessage);
var logFilePath = Path.Combine(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath, "transcode-" + Guid.NewGuid() + ".txt");
- Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
+ FileSystem.CreateDirectory(Path.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, FileMode.Create, FileAccess.Write, FileShare.Read, true);
@@ -144,7 +144,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
new JobLogger(Logger).StartStreamingLog(encodingJob, process.StandardError.BaseStream, encodingJob.LogFileStream);
// Wait for the file to exist before proceeeding
- while (!File.Exists(encodingJob.OutputFilePath) && !encodingJob.HasExited)
+ while (!FileSystem.FileExists(encodingJob.OutputFilePath) && !encodingJob.HasExited)
{
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
}
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 5d5e76074..fe300e2c4 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -7,6 +7,7 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Session;
using MediaBrowser.MediaEncoding.Probing;
using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.IO;
@@ -96,6 +97,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
FFMpegPath = ffMpegPath;
}
+ public void SetAvailableEncoders(List<string> list)
+ {
+
+ }
+
+ private List<string> _decoders = new List<string>();
+ public void SetAvailableDecoders(List<string> list)
+ {
+ _decoders = list.ToList();
+ }
+
+ public bool SupportsDecoder(string decoder)
+ {
+ return _decoders.Contains(decoder, StringComparer.OrdinalIgnoreCase);
+ }
+
/// <summary>
/// Gets the encoder path.
/// </summary>
@@ -243,14 +260,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (extractKeyFrameInterval && mediaInfo.RunTimeTicks.HasValue)
{
- if (ConfigurationManager.Configuration.EnableVideoFrameAnalysis && mediaInfo.Size.HasValue && mediaInfo.Size.Value <= ConfigurationManager.Configuration.VideoFrameAnalysisLimitBytes)
+ if (ConfigurationManager.Configuration.EnableVideoFrameByFrameAnalysis && mediaInfo.Size.HasValue)
{
foreach (var stream in mediaInfo.MediaStreams)
{
- if (stream.Type == MediaStreamType.Video &&
- string.Equals(stream.Codec, "h264", StringComparison.OrdinalIgnoreCase) &&
- !stream.IsInterlaced &&
- !(stream.IsAnamorphic ?? false))
+ if (EnableKeyframeExtraction(mediaInfo, stream))
{
try
{
@@ -287,6 +301,25 @@ namespace MediaBrowser.MediaEncoding.Encoder
throw new ApplicationException(string.Format("FFProbe failed for {0}", inputPath));
}
+ private bool EnableKeyframeExtraction(MediaSourceInfo mediaSource, MediaStream videoStream)
+ {
+ if (videoStream.Type == MediaStreamType.Video && string.Equals(videoStream.Codec, "h264", StringComparison.OrdinalIgnoreCase) &&
+ !videoStream.IsInterlaced &&
+ !(videoStream.IsAnamorphic ?? false))
+ {
+ var audioStreams = mediaSource.MediaStreams.Where(i => i.Type == MediaStreamType.Audio).ToList();
+
+ // If it has aac audio then it will probably direct stream anyway, so don't bother with this
+ if (audioStreams.Count == 1 && string.Equals(audioStreams[0].Codec, "aac", StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+
+ return true;
+ }
+ return false;
+ }
+
private async Task<List<int>> GetKeyFrames(string inputPath, int videoStreamIndex, CancellationToken cancellationToken)
{
inputPath = inputPath.Split(new[] { ':' }, 2).Last().Trim('"');
@@ -313,7 +346,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
EnableRaisingEvents = true
};
- _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
+ _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
using (process)
{
@@ -339,7 +372,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
process.WaitForExit();
- _logger.Debug("Keyframe extraction took {0} seconds", (DateTime.UtcNow - start).TotalSeconds);
+ _logger.Info("Keyframe extraction took {0} seconds", (DateTime.UtcNow - start).TotalSeconds);
//_logger.Debug("Found keyframes {0}", string.Join(",", lines.ToArray()));
return lines;
}
@@ -466,9 +499,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
}
- // TODO: Output in webp for smaller sizes
- // -f image2 -f webp
-
// Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case.
var args = useIFrame ? string.Format("-i {0} -threads 1 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, "-", vf) :
string.Format("-i {0} -threads 1 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf);
@@ -588,7 +618,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
vf += string.Format(",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam);
}
- Directory.CreateDirectory(targetDirectory);
+ FileSystem.CreateDirectory(targetDirectory);
var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg");
var args = string.Format("-i {0} -threads 1 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf);
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index 0226dbc5a..7cf2425a9 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -516,12 +516,25 @@ namespace MediaBrowser.MediaEncoding.Probing
FetchStudios(audio, tags, "label");
// These support mulitple values, but for now we only store the first.
- audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")));
-
- audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzTrack, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")));
+ var mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id"));
+ if(mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMARTISTID"));
+ audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, mb);
+
+ mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id"));
+ if(mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ARTISTID"));
+ audio.SetProviderId(MetadataProviders.MusicBrainzArtist, mb);
+
+ mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id"));
+ if(mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_ALBUMID"));
+ audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, mb);
+
+ mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id"));
+ if(mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASEGROUPID"));
+ audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, mb);
+
+ mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id"));
+ if(mb == null) mb = GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MUSICBRAINZ_RELEASETRACKID"));
+ audio.SetProviderId(MetadataProviders.MusicBrainzTrack, mb);
}
private string GetMultipleMusicBrainzId(string value)
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs
index d40d4afa7..2a6aa993c 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs
@@ -69,7 +69,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
subEvent.Text = string.Join(ParserValues.NewLine, multiline);
subEvent.Text = subEvent.Text.Replace(@"\N", ParserValues.NewLine, StringComparison.OrdinalIgnoreCase);
- subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase);
+ subEvent.Text = Regex.Replace(subEvent.Text, @"\{(?:\\\d?[\w.-]+(?:\([^\)]*\)|&H?[0-9A-Fa-f]+&|))+\}", string.Empty, RegexOptions.IgnoreCase);
subEvent.Text = Regex.Replace(subEvent.Text, "<", "&lt;", RegexOptions.IgnoreCase);
subEvent.Text = Regex.Replace(subEvent.Text, ">", "&gt;", RegexOptions.IgnoreCase);
subEvent.Text = Regex.Replace(subEvent.Text, "&lt;(\\/?(font|b|u|i|s))((\\s+(\\w|\\w[\\w\\-]*\\w)(\\s*=\\s*(?:\\\".*?\\\"|'.*?'|[^'\\\">\\s]+))?)+\\s*|\\s*)(\\/?)&gt;", "<$1$3$7>", RegexOptions.IgnoreCase);
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 9d43cafb8..ea4c72b2f 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -183,7 +183,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
}
- return File.OpenRead(path);
+ return _fileSystem.OpenRead(path);
}
private Encoding GetEncoding(string charset)
@@ -346,7 +346,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
try
{
- if (!File.Exists(outputPath))
+ if (!_fileSystem.FileExists(outputPath))
{
await ConvertTextSubtitleToSrtInternal(inputPath, inputProtocol, outputPath, cancellationToken).ConfigureAwait(false);
}
@@ -383,7 +383,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
throw new ArgumentNullException("outputPath");
}
- Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
var encodingParam = await GetSubtitleFileCharacterSet(inputPath, inputProtocol, cancellationToken).ConfigureAwait(false);
@@ -413,7 +413,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-convert-" + Guid.NewGuid() + ".txt");
- Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath));
var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read,
true);
@@ -466,7 +466,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
failed = true;
- if (File.Exists(outputPath))
+ if (_fileSystem.FileExists(outputPath))
{
try
{
@@ -479,7 +479,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
}
}
- else if (!File.Exists(outputPath))
+ else if (!_fileSystem.FileExists(outputPath))
{
failed = true;
}
@@ -515,7 +515,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
try
{
- if (!File.Exists(outputPath))
+ if (!_fileSystem.FileExists(outputPath))
{
await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), subtitleStreamIndex,
outputCodec, outputPath, cancellationToken).ConfigureAwait(false);
@@ -540,7 +540,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
throw new ArgumentNullException("outputPath");
}
- Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath,
subtitleStreamIndex, outputCodec, outputPath);
@@ -566,7 +566,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
_logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-extract-" + Guid.NewGuid() + ".txt");
- Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath));
var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read,
true);
@@ -635,7 +635,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
_logger.ErrorException("Error deleting extracted subtitle {0}", ex, outputPath);
}
}
- else if (!File.Exists(outputPath))
+ else if (!_fileSystem.FileExists(outputPath))
{
failed = true;
}
diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
index 7d813e903..40e532b79 100644
--- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
+++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
@@ -1184,15 +1184,6 @@
<Compile Include="..\MediaBrowser.Model\Tasks\TaskTriggerInfo.cs">
<Link>Tasks\TaskTriggerInfo.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Themes\AppTheme.cs">
- <Link>Themes\AppTheme.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Themes\AppThemeInfo.cs">
- <Link>Themes\AppThemeInfo.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Themes\ThemeImage.cs">
- <Link>Themes\ThemeImage.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Updates\CheckForUpdateResult.cs">
<Link>Updates\CheckForUpdateResult.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
index 8605a0ab3..09a7cde9d 100644
--- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
+++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
@@ -1140,15 +1140,6 @@
<Compile Include="..\MediaBrowser.Model\Tasks\TaskTriggerInfo.cs">
<Link>Tasks\TaskTriggerInfo.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Themes\AppTheme.cs">
- <Link>Themes\AppTheme.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Themes\AppThemeInfo.cs">
- <Link>Themes\AppThemeInfo.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Themes\ThemeImage.cs">
- <Link>Themes\ThemeImage.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Updates\CheckForUpdateResult.cs">
<Link>Updates\CheckForUpdateResult.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs
index 6d3894f02..77b894eb8 100644
--- a/MediaBrowser.Model/Configuration/EncodingOptions.cs
+++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs
@@ -6,14 +6,13 @@ namespace MediaBrowser.Model.Configuration
public int EncodingThreadCount { get; set; }
public string TranscodingTempPath { get; set; }
public double DownMixAudioBoost { get; set; }
- public string H264Encoder { get; set; }
public bool EnableDebugLogging { get; set; }
public bool EnableThrottling { get; set; }
public int ThrottleThresholdInSeconds { get; set; }
+ public string HardwareVideoDecoder { get; set; }
public EncodingOptions()
{
- H264Encoder = "libx264";
DownMixAudioBoost = 2;
EnableThrottling = true;
ThrottleThresholdInSeconds = 120;
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 9f95953cf..b137a8502 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -45,12 +45,6 @@ namespace MediaBrowser.Model.Configuration
public bool EnableHttps { get; set; }
/// <summary>
- /// Gets or sets a value indicating whether [enable user specific user views].
- /// </summary>
- /// <value><c>true</c> if [enable user specific user views]; otherwise, <c>false</c>.</value>
- public bool EnableUserSpecificUserViews { get; set; }
-
- /// <summary>
/// Gets or sets the value pointing to the file system where the ssl certiifcate is located..
/// </summary>
/// <value>The value pointing to the file system where the ssl certiifcate is located..</value>
@@ -103,6 +97,12 @@ namespace MediaBrowser.Model.Configuration
/// </summary>
/// <value><c>true</c> if [disable startup scan]; otherwise, <c>false</c>.</value>
public bool DisableStartupScan { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether [enable user views].
+ /// </summary>
+ /// <value><c>true</c> if [enable user views]; otherwise, <c>false</c>.</value>
+ public bool EnableUserViews { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable library metadata sub folder].
@@ -222,8 +222,7 @@ namespace MediaBrowser.Model.Configuration
public bool DisableXmlSavers { get; set; }
public bool EnableWindowsShortcuts { get; set; }
- public bool EnableVideoFrameAnalysis { get; set; }
- public long VideoFrameAnalysisLimitBytes { get; set; }
+ public bool EnableVideoFrameByFrameAnalysis { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
@@ -273,16 +272,11 @@ namespace MediaBrowser.Model.Configuration
PeopleMetadataOptions = new PeopleMetadataOptions();
- EnableVideoFrameAnalysis = true;
- VideoFrameAnalysisLimitBytes = 600000000;
+ EnableVideoFrameByFrameAnalysis = false;
InsecureApps9 = new[]
{
- "Chromecast",
- "iOS",
"Unknown app",
- "iPad",
- "iPhone",
"Windows Phone"
};
diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs
index 793036f40..fd3df9c76 100644
--- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs
+++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs
@@ -28,7 +28,6 @@ namespace MediaBrowser.Model.Dlna
// TODO: Implement
return true;
case ProfileConditionValue.Has64BitOffsets:
- // TODO: Implement
return true;
case ProfileConditionValue.IsAnamorphic:
return IsConditionSatisfied(condition, isAnamorphic);
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index e0cc1b705..43534efda 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -725,7 +725,7 @@ namespace MediaBrowser.Model.Dlna
public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, EncodingContext context, PlayMethod playMethod)
{
- if (playMethod != PlayMethod.Transcode)
+ if (playMethod != PlayMethod.Transcode && !subtitleStream.IsExternal)
{
// Look for supported embedded subs
foreach (SubtitleProfile profile in subtitleProfiles)
@@ -749,24 +749,27 @@ namespace MediaBrowser.Model.Dlna
// Look for an external profile that matches the stream type (text/graphical)
foreach (SubtitleProfile profile in subtitleProfiles)
- {
- bool requiresConversion = !StringHelper.EqualsIgnoreCase(subtitleStream.Codec, profile.Format);
+ {
+ if (profile.Method != SubtitleDeliveryMethod.External)
+ {
+ continue;
+ }
if (!profile.SupportsLanguage(subtitleStream.Language))
{
continue;
}
- if (profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format))
+ if (subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format))
{
- if (!requiresConversion)
- {
- return profile;
- }
+ bool requiresConversion = !StringHelper.EqualsIgnoreCase(subtitleStream.Codec, profile.Format);
- if (subtitleStream.SupportsExternalStream)
+ if (subtitleStream.IsTextSubtitleStream || !requiresConversion)
{
- return profile;
+ if (subtitleStream.SupportsExternalStream)
+ {
+ return profile;
+ }
}
// For sync we can handle the longer extraction times
diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs
index a1c075563..9400582c4 100644
--- a/MediaBrowser.Model/Dto/BaseItemDto.cs
+++ b/MediaBrowser.Model/Dto/BaseItemDto.cs
@@ -74,8 +74,6 @@ namespace MediaBrowser.Model.Dto
public string ShareUrl { get; set; }
public float? Metascore { get; set; }
-
- public bool? IsUnidentified { get; set; }
public bool? HasDynamicCategories { get; set; }
public int? AnimeSeriesIndex { get; set; }
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index 19c5c833a..2a86b96d6 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -12,10 +12,10 @@
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<FodyPath>..\packages\Fody.1.19.1.0</FodyPath>
- <ProductVersion>10.0.0</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<RestorePackages>true</RestorePackages>
+ <ReleaseVersion>
+ </ReleaseVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -26,7 +26,6 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -35,7 +34,6 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Mono|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -44,15 +42,11 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<PropertyGroup>
- <SignAssembly>false</SignAssembly>
- </PropertyGroup>
- <PropertyGroup>
<AssemblyOriginatorKeyFile>MediaBrowser.Model.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
@@ -408,9 +402,6 @@
<Compile Include="Sync\SyncTarget.cs" />
<Compile Include="System\LogFile.cs" />
<Compile Include="System\PublicSystemInfo.cs" />
- <Compile Include="Themes\AppTheme.cs" />
- <Compile Include="Themes\AppThemeInfo.cs" />
- <Compile Include="Themes\ThemeImage.cs" />
<Compile Include="Updates\CheckForUpdateResult.cs" />
<Compile Include="Updates\PackageTargetSystem.cs" />
<Compile Include="Updates\InstallationInfo.cs" />
@@ -465,7 +456,7 @@
<HintPath>..\packages\PropertyChanged.Fody.1.41.0.0\Lib\NET35\PropertyChanged.dll</HintPath>
<Private>False</Private>
</Reference>
- <Reference Include="System.XML" />
+ <Reference Include="System.Xml" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs
index efa5a5217..e905af58d 100644
--- a/MediaBrowser.Model/Net/MimeTypes.cs
+++ b/MediaBrowser.Model/Net/MimeTypes.cs
@@ -318,7 +318,7 @@ namespace MediaBrowser.Model.Net
{
return result;
}
- throw new ArgumentNullException("Unable to determine extension for mimeType: " + mimeType);
+ return null;
}
}
}
diff --git a/MediaBrowser.Model/Themes/AppTheme.cs b/MediaBrowser.Model/Themes/AppTheme.cs
deleted file mode 100644
index 527f1de72..000000000
--- a/MediaBrowser.Model/Themes/AppTheme.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using System.Collections.Generic;
-
-namespace MediaBrowser.Model.Themes
-{
- public class AppTheme
- {
- public string AppName { get; set; }
-
- public string Name { get; set; }
-
- public Dictionary<string, string> Options { get; set; }
-
- public List<ThemeImage> Images { get; set; }
-
- public AppTheme()
- {
- Options = new Dictionary<string, string>();
-
- Images = new List<ThemeImage>();
- }
- }
-}
diff --git a/MediaBrowser.Model/Themes/AppThemeInfo.cs b/MediaBrowser.Model/Themes/AppThemeInfo.cs
deleted file mode 100644
index bc359530a..000000000
--- a/MediaBrowser.Model/Themes/AppThemeInfo.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace MediaBrowser.Model.Themes
-{
- public class AppThemeInfo
- {
- public string AppName { get; set; }
-
- public string Name { get; set; }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Model/Themes/ThemeImage.cs b/MediaBrowser.Model/Themes/ThemeImage.cs
deleted file mode 100644
index 2fe0820ae..000000000
--- a/MediaBrowser.Model/Themes/ThemeImage.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-
-namespace MediaBrowser.Model.Themes
-{
- public class ThemeImage
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the cache tag.
- /// </summary>
- /// <value>The cache tag.</value>
- public string CacheTag { get; set; }
- }
-}
diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
index 0e7050741..0fbb2d990 100644
--- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
+++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
@@ -156,7 +156,7 @@ namespace MediaBrowser.Providers.BoxSets
var dataFilePath = GetDataFilePath(_config.ApplicationPaths, tmdbId, preferredMetadataLanguage);
- Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_json.SerializeToFile(mainResult, dataFilePath);
}
diff --git a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs
index 13e486ae9..114346191 100644
--- a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs
+++ b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs
@@ -77,11 +77,11 @@ namespace MediaBrowser.Providers.Folders
if (string.Equals(viewType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))
{
- return urlPrefix + "books.png";
+ //return urlPrefix + "books.png";
}
if (string.Equals(viewType, CollectionType.Games, StringComparison.OrdinalIgnoreCase))
{
- return urlPrefix + "games.png";
+ //return urlPrefix + "games.png";
}
if (string.Equals(viewType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
{
@@ -109,23 +109,23 @@ namespace MediaBrowser.Providers.Folders
}
if (string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
{
- return urlPrefix + "playlists.png";
+ //return urlPrefix + "playlists.png";
}
if (string.Equals(viewType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
{
- return urlPrefix + "homevideos.png";
+ //return urlPrefix + "homevideos.png";
}
if (string.Equals(viewType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
{
- return urlPrefix + "musicvideos.png";
+ //return urlPrefix + "musicvideos.png";
}
if (string.Equals(viewType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
{
- return urlPrefix + "generic.png";
+ //return urlPrefix + "generic.png";
}
if (string.IsNullOrWhiteSpace(viewType))
{
- return urlPrefix + "generic.png";
+ //return urlPrefix + "generic.png";
}
return null;
diff --git a/MediaBrowser.Providers/ImagesByName/ImageUtils.cs b/MediaBrowser.Providers/ImagesByName/ImageUtils.cs
index 72df3697a..ae2421f65 100644
--- a/MediaBrowser.Providers/ImagesByName/ImageUtils.cs
+++ b/MediaBrowser.Providers/ImagesByName/ImageUtils.cs
@@ -40,9 +40,9 @@ namespace MediaBrowser.Providers.ImagesByName
}).ConfigureAwait(false);
- Directory.CreateDirectory(Path.GetDirectoryName(file));
+ fileSystem.CreateDirectory(Path.GetDirectoryName(file));
- File.Copy(temp, file, true);
+ fileSystem.CopyFile(temp, file, true);
}
finally
{
diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs
index 22178434f..624736779 100644
--- a/MediaBrowser.Providers/Manager/ImageSaver.cs
+++ b/MediaBrowser.Providers/Manager/ImageSaver.cs
@@ -208,7 +208,7 @@ namespace MediaBrowser.Providers.Manager
try
{
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
// If the file is currently hidden we'll have to remove that or the save will fail
var file = new FileInfo(path);
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index 92fc1c2a8..3c412b788 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -358,7 +358,7 @@ namespace MediaBrowser.Providers.Manager
if (deleted)
{
- item.ValidateImages(new DirectoryService(_logger));
+ item.ValidateImages(new DirectoryService(_logger, _fileSystem));
}
}
@@ -392,7 +392,7 @@ namespace MediaBrowser.Providers.Manager
else
{
var existing = item.GetImageInfo(type, 0);
- if (existing != null && !File.Exists(existing.Path))
+ if (existing != null && !_fileSystem.FileExists(existing.Path))
{
item.RemoveImage(existing);
changed = true;
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index cddc6f894..8a60ea78f 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -147,7 +147,14 @@ namespace MediaBrowser.Providers.Manager
updateType = updateType | result.UpdateType;
refreshResult.AddStatus(result.Status, result.ErrorMessage);
- refreshResult.SetDateLastMetadataRefresh(DateTime.UtcNow);
+ if (result.Failures == 0)
+ {
+ refreshResult.SetDateLastMetadataRefresh(DateTime.UtcNow);
+ }
+ else
+ {
+ refreshResult.SetDateLastMetadataRefresh(null);
+ }
MergeIdentities(itemOfType, id);
}
@@ -164,7 +171,14 @@ namespace MediaBrowser.Providers.Manager
updateType = updateType | result.UpdateType;
refreshResult.AddStatus(result.Status, result.ErrorMessage);
- refreshResult.SetDateLastImagesRefresh(DateTime.UtcNow);
+ if (result.Failures == 0)
+ {
+ refreshResult.SetDateLastImagesRefresh(DateTime.UtcNow);
+ }
+ else
+ {
+ refreshResult.SetDateLastImagesRefresh(null);
+ }
}
}
@@ -503,7 +517,7 @@ namespace MediaBrowser.Providers.Manager
{
return false;
}
-
+
return true;
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index fe0e4890c..80264d848 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -283,17 +283,17 @@ namespace MediaBrowser.Providers.Manager
{
var options = GetMetadataOptions(item);
- return GetMetadataProvidersInternal<T>(item, options, false);
+ return GetMetadataProvidersInternal<T>(item, options, false, true);
}
- private IEnumerable<IMetadataProvider<T>> GetMetadataProvidersInternal<T>(IHasMetadata item, MetadataOptions options, bool includeDisabled)
+ private IEnumerable<IMetadataProvider<T>> GetMetadataProvidersInternal<T>(IHasMetadata item, MetadataOptions options, bool includeDisabled, bool checkIsOwnedItem)
where T : IHasMetadata
{
// Avoid implicitly captured closure
var currentOptions = options;
return _metadataProviders.OfType<IMetadataProvider<T>>()
- .Where(i => CanRefresh(i, item, currentOptions, includeDisabled))
+ .Where(i => CanRefresh(i, item, currentOptions, includeDisabled, checkIsOwnedItem))
.OrderBy(i => GetConfiguredOrder(i, options))
.ThenBy(GetDefaultOrder);
}
@@ -318,7 +318,7 @@ namespace MediaBrowser.Providers.Manager
return GetImageProviders(item, options, includeDisabled).OfType<IRemoteImageProvider>();
}
- private bool CanRefresh(IMetadataProvider provider, IHasMetadata item, MetadataOptions options, bool includeDisabled)
+ private bool CanRefresh(IMetadataProvider provider, IHasMetadata item, MetadataOptions options, bool includeDisabled, bool checkIsOwnedItem)
{
if (!includeDisabled)
{
@@ -348,7 +348,7 @@ namespace MediaBrowser.Providers.Manager
}
// If this restriction is ever lifted, movie xml providers will have to be updated to prevent owned items like trailers from reading those files
- if (item.IsOwnedItem)
+ if (checkIsOwnedItem && item.IsOwnedItem)
{
if (provider is ILocalMetadataProvider || provider is IRemoteMetadataProvider)
{
@@ -491,7 +491,8 @@ namespace MediaBrowser.Providers.Manager
// Give it a dummy path just so that it looks like a file system item
var dummy = new T()
{
- Path = Path.Combine(_appPaths.InternalMetadataPath, "dummy")
+ Path = Path.Combine(_appPaths.InternalMetadataPath, "dummy"),
+ ParentId = Guid.NewGuid()
};
dummy.SetParent(new Folder());
@@ -523,7 +524,7 @@ namespace MediaBrowser.Providers.Manager
private void AddMetadataPlugins<T>(List<MetadataPlugin> list, T item, MetadataOptions options)
where T : IHasMetadata
{
- var providers = GetMetadataProvidersInternal<T>(item, options, true).ToList();
+ var providers = GetMetadataProvidersInternal<T>(item, options, true, false).ToList();
// Locals
list.AddRange(providers.Where(i => (i is ILocalMetadataProvider)).Select(i => new MetadataPlugin
@@ -701,7 +702,7 @@ namespace MediaBrowser.Providers.Manager
// Manual edit occurred
// Even if save local is off, save locally anyway if the metadata file already exists
- if (fileSaver == null || !isEnabledFor || !File.Exists(fileSaver.GetSavePath(item)))
+ if (fileSaver == null || !isEnabledFor || !_fileSystem.FileExists(fileSaver.GetSavePath(item)))
{
return false;
}
@@ -732,14 +733,15 @@ namespace MediaBrowser.Providers.Manager
// Give it a dummy path just so that it looks like a file system item
var dummy = new TItemType
{
- Path = Path.Combine(_appPaths.InternalMetadataPath, "dummy")
+ Path = Path.Combine(_appPaths.InternalMetadataPath, "dummy"),
+ ParentId = Guid.NewGuid()
};
dummy.SetParent(new Folder());
var options = GetMetadataOptions(dummy);
- var providers = GetMetadataProvidersInternal<TItemType>(dummy, options, searchInfo.IncludeDisabledProviders)
+ var providers = GetMetadataProvidersInternal<TItemType>(dummy, options, searchInfo.IncludeDisabledProviders, false)
.OfType<IRemoteSearchProvider<TLookupType>>();
if (!string.IsNullOrEmpty(searchInfo.SearchProviderName))
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 1d323e567..1d12426b9 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -53,9 +53,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
</Reference>
- <Reference Include="MoreLinq, Version=1.1.17511.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL">
+ <Reference Include="MoreLinq, Version=1.1.18418.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\morelinq.1.1.0\lib\net35\MoreLinq.dll</HintPath>
+ <HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
</Reference>
<Reference Include="policy.2.0.taglib-sharp">
<HintPath>..\packages\taglib.2.1.0.0\lib\policy.2.0.taglib-sharp.dll</HintPath>
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index bd83862a8..43c5717e3 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -55,7 +55,7 @@ namespace MediaBrowser.Providers.MediaInfo
{
var path = GetAudioImagePath(item);
- if (!File.Exists(path))
+ if (!_fileSystem.FileExists(path))
{
var semaphore = GetLock(path);
@@ -65,9 +65,9 @@ namespace MediaBrowser.Providers.MediaInfo
try
{
// Check again in case it was saved while waiting for the lock
- if (!File.Exists(path))
+ if (!_fileSystem.FileExists(path))
{
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, cancellationToken).ConfigureAwait(false))
{
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
index c05f1b64b..2033107af 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
@@ -148,7 +148,7 @@ namespace MediaBrowser.Providers.MediaInfo
private void FetchShortcutInfo(Video video)
{
- video.ShortcutPath = File.ReadAllText(video.Path);
+ video.ShortcutPath = _fileSystem.ReadAllText(video.Path);
}
public Task<ItemUpdateType> FetchAudioInfo<T>(T item, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index 9fc8e1f8a..1f245541a 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -706,7 +706,7 @@ namespace MediaBrowser.Providers.MediaInfo
// Try to eliminate menus and intros by skipping all files at the front of the list that are less than the minimum size
// Once we reach a file that is at least the minimum, return all subsequent ones
- var allVobs = new DirectoryInfo(root).EnumerateFiles("*", SearchOption.AllDirectories)
+ var allVobs = _fileSystem.GetFiles(root)
.Where(file => string.Equals(file.Extension, ".vob", StringComparison.OrdinalIgnoreCase))
.OrderBy(i => i.FullName)
.ToList();
diff --git a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs
index f133f74db..8d0437f05 100644
--- a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs
+++ b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs
@@ -66,7 +66,7 @@ namespace MediaBrowser.Providers.Movies
var path = FanartMovieImageProvider.GetMoviesDataPath(_config.CommonApplicationPaths);
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
var timestampFile = Path.Combine(path, "time.txt");
@@ -79,7 +79,7 @@ namespace MediaBrowser.Providers.Movies
}
// Find out the last time we queried for updates
- var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
+ var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList();
@@ -95,7 +95,7 @@ namespace MediaBrowser.Providers.Movies
var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture);
- File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
+ _fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
progress.Report(100);
}
diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
index 8d0c5cd54..3cf0c42b6 100644
--- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
+++ b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
@@ -293,7 +293,7 @@ namespace MediaBrowser.Providers.Movies
var path = GetFanartJsonPath(id);
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
try
{
diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
index f5ee33d6b..d171c4aa4 100644
--- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
+++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs
@@ -13,6 +13,7 @@ using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Providers.Movies
{
@@ -22,14 +23,16 @@ namespace MediaBrowser.Providers.Movies
private readonly ILogger _logger;
private readonly IJsonSerializer _jsonSerializer;
private readonly ILibraryManager _libraryManager;
+ private readonly IFileSystem _fileSystem;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- public GenericMovieDbInfo(ILogger logger, IJsonSerializer jsonSerializer, ILibraryManager libraryManager)
+ public GenericMovieDbInfo(ILogger logger, IJsonSerializer jsonSerializer, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_logger = logger;
_jsonSerializer = jsonSerializer;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
public async Task<MetadataResult<T>> GetMetadata(ItemLookupInfo itemId, CancellationToken cancellationToken)
@@ -88,7 +91,7 @@ namespace MediaBrowser.Providers.Movies
tmdbId = movieInfo.id.ToString(_usCulture);
dataFilePath = MovieDbProvider.Current.GetDataFilePath(tmdbId, language);
- Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(movieInfo, dataFilePath);
}
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index 48b7140f8..4136d3601 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -115,7 +115,7 @@ namespace MediaBrowser.Providers.Movies
public Task<MetadataResult<T>> GetItemMetadata<T>(ItemLookupInfo id, CancellationToken cancellationToken)
where T : BaseItem, new()
{
- var movieDb = new GenericMovieDbInfo<T>(_logger, _jsonSerializer, _libraryManager);
+ var movieDb = new GenericMovieDbInfo<T>(_logger, _jsonSerializer, _libraryManager, _fileSystem);
return movieDb.GetMetadata(id, cancellationToken);
}
@@ -210,7 +210,7 @@ namespace MediaBrowser.Providers.Movies
var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage);
- Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
diff --git a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs
index cc2142292..586e9ad40 100644
--- a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs
+++ b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs
@@ -76,7 +76,7 @@ namespace MediaBrowser.Providers.Movies
var path = MovieDbProvider.GetMoviesDataPath(_config.CommonApplicationPaths);
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
var timestampFile = Path.Combine(path, "time.txt");
@@ -89,7 +89,7 @@ namespace MediaBrowser.Providers.Movies
}
// Find out the last time we queried tvdb for updates
- var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
+ var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList();
@@ -117,7 +117,7 @@ namespace MediaBrowser.Providers.Movies
}
}
- File.WriteAllText(timestampFile, DateTime.UtcNow.Ticks.ToString(UsCulture), Encoding.UTF8);
+ _fileSystem.WriteAllText(timestampFile, DateTime.UtcNow.Ticks.ToString(UsCulture), Encoding.UTF8);
progress.Report(100);
}
diff --git a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
index 3667d70cf..6437d2471 100644
--- a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
@@ -125,7 +125,7 @@ namespace MediaBrowser.Providers.Music
var path = GetAlbumInfoPath(_config.ApplicationPaths, musicBrainzReleaseGroupId);
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.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 eefa1a2f4..5164c7df4 100644
--- a/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/AudioDbArtistProvider.cs
@@ -121,7 +121,7 @@ namespace MediaBrowser.Providers.Music
}).ConfigureAwait(false))
{
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
using (var xmlFileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
index 597c5c0bc..7076a0016 100644
--- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
@@ -433,7 +433,7 @@ namespace MediaBrowser.Providers.Music
var xmlPath = GetArtistXmlPath(_config.ApplicationPaths, musicBrainzId);
- Directory.CreateDirectory(Path.GetDirectoryName(xmlPath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(xmlPath));
using (var response = await _httpClient.Get(new HttpRequestOptions
{
diff --git a/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs b/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs
index a9b05c99f..86fb0899f 100644
--- a/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs
+++ b/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs
@@ -65,7 +65,7 @@ namespace MediaBrowser.Providers.Music
var path = FanartArtistProvider.GetArtistDataPath(_config.CommonApplicationPaths);
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
var timestampFile = Path.Combine(path, "time.txt");
@@ -78,7 +78,7 @@ namespace MediaBrowser.Providers.Music
}
// Find out the last time we queried for updates
- var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
+ var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList();
@@ -94,7 +94,7 @@ namespace MediaBrowser.Providers.Music
var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture);
- File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
+ _fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
progress.Report(100);
}
diff --git a/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs
index 7f804f9df..3f25f0f93 100644
--- a/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs
@@ -79,8 +79,7 @@ namespace MediaBrowser.Providers.Omdb
public bool Supports(IHasImages item)
{
- // Save the http requests since we know it's not currently supported
- // TODO: Check again periodically
+ // We'll hammer Omdb if we enable this
if (item is Person)
{
return false;
diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
index dd4231f3f..829296401 100644
--- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
+++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
@@ -200,7 +200,7 @@ namespace MediaBrowser.Providers.People
}).ConfigureAwait(false))
{
- Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
using (var fs = _fileSystem.GetFileStream(dataFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
{
diff --git a/MediaBrowser.Providers/Photos/PhotoProvider.cs b/MediaBrowser.Providers/Photos/PhotoProvider.cs
index b635d4ead..ef3144958 100644
--- a/MediaBrowser.Providers/Photos/PhotoProvider.cs
+++ b/MediaBrowser.Providers/Photos/PhotoProvider.cs
@@ -31,110 +31,111 @@ namespace MediaBrowser.Providers.Photos
try
{
- var file = File.Create(item.Path);
-
- var image = file as TagLib.Image.File;
-
- var tag = file.GetTag(TagTypes.TiffIFD) as IFDTag;
-
- if (tag != null)
+ using (var file = TagLib.File.Create(item.Path))
{
- var structure = tag.Structure;
+ var image = file as TagLib.Image.File;
- if (structure != null)
+ var tag = file.GetTag(TagTypes.TiffIFD) as IFDTag;
+
+ if (tag != null)
{
- var exif = structure.GetEntry(0, (ushort)IFDEntryTag.ExifIFD) as SubIFDEntry;
+ var structure = tag.Structure;
- if (exif != null)
+ if (structure != null)
{
- var exifStructure = exif.Structure;
+ var exif = structure.GetEntry(0, (ushort)IFDEntryTag.ExifIFD) as SubIFDEntry;
- if (exifStructure != null)
+ if (exif != null)
{
- var entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ApertureValue) as RationalIFDEntry;
+ var exifStructure = exif.Structure;
- if (entry != null)
+ if (exifStructure != null)
{
- double val = entry.Value.Numerator;
- val /= entry.Value.Denominator;
- item.Aperture = val;
- }
-
- entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ShutterSpeedValue) as RationalIFDEntry;
-
- if (entry != null)
- {
- double val = entry.Value.Numerator;
- val /= entry.Value.Denominator;
- item.ShutterSpeed = val;
+ var entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ApertureValue) as RationalIFDEntry;
+
+ if (entry != null)
+ {
+ double val = entry.Value.Numerator;
+ val /= entry.Value.Denominator;
+ item.Aperture = val;
+ }
+
+ entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ShutterSpeedValue) as RationalIFDEntry;
+
+ if (entry != null)
+ {
+ double val = entry.Value.Numerator;
+ val /= entry.Value.Denominator;
+ item.ShutterSpeed = val;
+ }
}
}
}
}
- }
-
- item.CameraMake = image.ImageTag.Make;
- item.CameraModel = image.ImageTag.Model;
- item.Width = image.Properties.PhotoWidth;
- item.Height = image.Properties.PhotoHeight;
+ item.CameraMake = image.ImageTag.Make;
+ item.CameraModel = image.ImageTag.Model;
- var rating = image.ImageTag.Rating;
- if (rating.HasValue)
- {
- item.CommunityRating = rating;
- }
- else
- {
- item.CommunityRating = null;
- }
+ item.Width = image.Properties.PhotoWidth;
+ item.Height = image.Properties.PhotoHeight;
- item.Overview = image.ImageTag.Comment;
+ var rating = image.ImageTag.Rating;
+ if (rating.HasValue)
+ {
+ item.CommunityRating = rating;
+ }
+ else
+ {
+ item.CommunityRating = null;
+ }
- if (!string.IsNullOrWhiteSpace(image.ImageTag.Title))
- {
- item.Name = image.ImageTag.Title;
- }
+ item.Overview = image.ImageTag.Comment;
- var dateTaken = image.ImageTag.DateTime;
- if (dateTaken.HasValue)
- {
- item.DateCreated = dateTaken.Value;
- item.PremiereDate = dateTaken.Value;
- item.ProductionYear = dateTaken.Value.Year;
- }
+ if (!string.IsNullOrWhiteSpace(image.ImageTag.Title))
+ {
+ item.Name = image.ImageTag.Title;
+ }
- item.Genres = image.ImageTag.Genres.ToList();
- item.Tags = image.ImageTag.Keywords.ToList();
- item.Software = image.ImageTag.Software;
+ var dateTaken = image.ImageTag.DateTime;
+ if (dateTaken.HasValue)
+ {
+ item.DateCreated = dateTaken.Value;
+ item.PremiereDate = dateTaken.Value;
+ item.ProductionYear = dateTaken.Value.Year;
+ }
- if (image.ImageTag.Orientation == TagLib.Image.ImageOrientation.None)
- {
- item.Orientation = null;
- }
- else
- {
- Model.Drawing.ImageOrientation orientation;
- if (Enum.TryParse(image.ImageTag.Orientation.ToString(), true, out orientation))
+ item.Genres = image.ImageTag.Genres.ToList();
+ item.Tags = image.ImageTag.Keywords.ToList();
+ item.Software = image.ImageTag.Software;
+
+ if (image.ImageTag.Orientation == TagLib.Image.ImageOrientation.None)
{
- item.Orientation = orientation;
+ item.Orientation = null;
+ }
+ else
+ {
+ Model.Drawing.ImageOrientation orientation;
+ if (Enum.TryParse(image.ImageTag.Orientation.ToString(), true, out orientation))
+ {
+ item.Orientation = orientation;
+ }
}
- }
- item.ExposureTime = image.ImageTag.ExposureTime;
- item.FocalLength = image.ImageTag.FocalLength;
+ item.ExposureTime = image.ImageTag.ExposureTime;
+ item.FocalLength = image.ImageTag.FocalLength;
- item.Latitude = image.ImageTag.Latitude;
- item.Longitude = image.ImageTag.Longitude;
- item.Altitude = image.ImageTag.Altitude;
+ item.Latitude = image.ImageTag.Latitude;
+ item.Longitude = image.ImageTag.Longitude;
+ item.Altitude = image.ImageTag.Altitude;
- if (image.ImageTag.ISOSpeedRatings.HasValue)
- {
- item.IsoSpeedRating = Convert.ToInt32(image.ImageTag.ISOSpeedRatings.Value);
- }
- else
- {
- item.IsoSpeedRating = null;
+ if (image.ImageTag.ISOSpeedRatings.HasValue)
+ {
+ item.IsoSpeedRating = Convert.ToInt32(image.ImageTag.ISOSpeedRatings.Value);
+ }
+ else
+ {
+ item.IsoSpeedRating = null;
+ }
}
}
catch (Exception e)
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
index c449edd07..b07f5b00a 100644
--- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -252,7 +252,7 @@ namespace MediaBrowser.Providers.Subtitles
_monitor.ReportFileSystemChangeComplete(path, false);
}
- return _libraryManager.GetItemById(itemId).RefreshMetadata(new MetadataRefreshOptions(new DirectoryService())
+ return _libraryManager.GetItemById(itemId).RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_fileSystem))
{
ImageRefreshMode = ImageRefreshMode.ValidationOnly,
MetadataRefreshMode = MetadataRefreshMode.ValidationOnly
diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs
index 426ff4318..c61b4f279 100644
--- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs
@@ -10,6 +10,7 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Providers.TV
{
@@ -19,15 +20,17 @@ namespace MediaBrowser.Providers.TV
private readonly ILogger _logger;
private readonly ILocalizationManager _localization;
private readonly ILibraryManager _libraryManager;
+ private readonly IFileSystem _fileSystem;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- public DummySeasonProvider(IServerConfigurationManager config, ILogger logger, ILocalizationManager localization, ILibraryManager libraryManager)
+ public DummySeasonProvider(IServerConfigurationManager config, ILogger logger, ILocalizationManager localization, ILibraryManager libraryManager, IFileSystem fileSystem)
{
_config = config;
_logger = logger;
_localization = localization;
_libraryManager = libraryManager;
+ _fileSystem = fileSystem;
}
public async Task Run(Series series, CancellationToken cancellationToken)
@@ -38,7 +41,7 @@ namespace MediaBrowser.Providers.TV
if (hasNewSeasons)
{
- var directoryService = new DirectoryService();
+ var directoryService = new DirectoryService(_fileSystem);
//await series.RefreshMetadata(new MetadataRefreshOptions(directoryService), cancellationToken).ConfigureAwait(false);
@@ -118,7 +121,7 @@ namespace MediaBrowser.Providers.TV
await series.AddChild(season, cancellationToken).ConfigureAwait(false);
- await season.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken).ConfigureAwait(false);
+ await season.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken).ConfigureAwait(false);
return season;
}
diff --git a/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs b/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs
index 64c6488fb..32fd0b119 100644
--- a/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs
+++ b/MediaBrowser.Providers/TV/FanArtTvUpdatesPostScanTask.cs
@@ -65,7 +65,7 @@ namespace MediaBrowser.Providers.TV
var path = FanartSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
var timestampFile = Path.Combine(path, "time.txt");
@@ -78,7 +78,7 @@ namespace MediaBrowser.Providers.TV
}
// Find out the last time we queried for updates
- var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
+ var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
var existingDirectories = Directory.EnumerateDirectories(path).Select(Path.GetFileName).ToList();
@@ -94,7 +94,7 @@ namespace MediaBrowser.Providers.TV
var newUpdateTime = Convert.ToInt64(DateTimeToUnixTimestamp(DateTime.UtcNow)).ToString(UsCulture);
- File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
+ _fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
progress.Report(100);
}
diff --git a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanartSeriesProvider.cs
index 6af2aa38d..a353ef4bd 100644
--- a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/FanartSeriesProvider.cs
@@ -309,7 +309,7 @@ namespace MediaBrowser.Providers.TV
var path = GetFanartJsonPath(tvdbId);
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
try
{
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index 957345607..1443c524f 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -15,6 +15,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Providers.TV
{
@@ -24,15 +25,17 @@ namespace MediaBrowser.Providers.TV
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _localization;
+ private readonly IFileSystem _fileSystem;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization)
+ public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, IFileSystem fileSystem)
{
_logger = logger;
_config = config;
_libraryManager = libraryManager;
_localization = localization;
+ _fileSystem = fileSystem;
}
public async Task Run(IEnumerable<IGrouping<string, Series>> series, CancellationToken cancellationToken)
@@ -119,7 +122,7 @@ namespace MediaBrowser.Providers.TV
{
foreach (var series in group)
{
- var directoryService = new DirectoryService();
+ var directoryService = new DirectoryService(_fileSystem);
await series.RefreshMetadata(new MetadataRefreshOptions(directoryService)
{
@@ -395,7 +398,7 @@ namespace MediaBrowser.Providers.TV
if (season == null)
{
- var provider = new DummySeasonProvider(_config, _logger, _localization, _libraryManager);
+ var provider = new DummySeasonProvider(_config, _logger, _localization, _libraryManager, _fileSystem);
season = await provider.AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false);
}
@@ -413,7 +416,7 @@ namespace MediaBrowser.Providers.TV
await season.AddChild(episode, cancellationToken).ConfigureAwait(false);
- await episode.RefreshMetadata(new MetadataRefreshOptions
+ await episode.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
{
}, cancellationToken).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs
index ff5e6025d..aaa9bbacf 100644
--- a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs
@@ -206,7 +206,7 @@ namespace MediaBrowser.Providers.TV
var dataFilePath = GetDataFilePath(id, seasonNumber, episodeNumber, preferredMetadataLanguage);
- Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
diff --git a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs
index 44c36af8f..fb4ce2c37 100644
--- a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs
@@ -190,7 +190,7 @@ namespace MediaBrowser.Providers.TV
var dataFilePath = GetDataFilePath(id, seasonNumber, preferredMetadataLanguage);
- Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
diff --git a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs
index f861ad553..78595718d 100644
--- a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs
@@ -194,7 +194,7 @@ namespace MediaBrowser.Providers.TV
tmdbId = seriesInfo.id.ToString(_usCulture);
dataFilePath = GetDataFilePath(tmdbId, language);
- Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(seriesInfo, dataFilePath);
await EnsureSeriesInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
@@ -289,7 +289,7 @@ namespace MediaBrowser.Providers.TV
var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage);
- Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
index 0b2aaa5a0..24da853d3 100644
--- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
@@ -29,7 +29,7 @@ namespace MediaBrowser.Providers.TV
if (refreshOptions.IsPostRecursiveRefresh)
{
- var provider = new DummySeasonProvider(ServerConfigurationManager, Logger, _localization, LibraryManager);
+ var provider = new DummySeasonProvider(ServerConfigurationManager, Logger, _localization, LibraryManager, FileSystem);
try
{
diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
index 874b5c92d..f7a2dcefe 100644
--- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
+++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
@@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Providers.TV
{
@@ -27,13 +28,15 @@ namespace MediaBrowser.Providers.TV
private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
private readonly ILocalizationManager _localization;
+ private readonly IFileSystem _fileSystem;
- public SeriesPostScanTask(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, ILocalizationManager localization)
+ public SeriesPostScanTask(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, ILocalizationManager localization, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
_logger = logger;
_config = config;
_localization = localization;
+ _fileSystem = fileSystem;
}
public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
@@ -50,7 +53,7 @@ namespace MediaBrowser.Providers.TV
var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
- await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
+ await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
var numComplete = 0;
diff --git a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs
index 4bc4a2c8d..041f91355 100644
--- a/MediaBrowser.Providers/TV/TvdbPrescanTask.cs
+++ b/MediaBrowser.Providers/TV/TvdbPrescanTask.cs
@@ -89,7 +89,7 @@ namespace MediaBrowser.Providers.TV
var path = TvdbSeriesProvider.GetSeriesDataPath(_config.CommonApplicationPaths);
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
var timestampFile = Path.Combine(path, "time.txt");
@@ -102,7 +102,7 @@ namespace MediaBrowser.Providers.TV
}
// Find out the last time we queried tvdb for updates
- var lastUpdateTime = timestampFileInfo.Exists ? File.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
+ var lastUpdateTime = timestampFileInfo.Exists ? _fileSystem.ReadAllText(timestampFile, Encoding.UTF8) : string.Empty;
string newUpdateTime;
@@ -157,7 +157,7 @@ namespace MediaBrowser.Providers.TV
await UpdateSeries(listToUpdate, path, nullableUpdateValue, progress, cancellationToken).ConfigureAwait(false);
}
- File.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
+ _fileSystem.WriteAllText(timestampFile, newUpdateTime, Encoding.UTF8);
progress.Report(100);
}
@@ -357,7 +357,7 @@ namespace MediaBrowser.Providers.TV
seriesDataPath = Path.Combine(seriesDataPath, id);
- Directory.CreateDirectory(seriesDataPath);
+ _fileSystem.CreateDirectory(seriesDataPath);
return TvdbSeriesProvider.Current.DownloadSeriesZip(id, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, cancellationToken);
}
diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
index 3298fbc76..56e9dbd03 100644
--- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
@@ -252,7 +252,7 @@ namespace MediaBrowser.Providers.TV
if (!string.Equals(downloadLangaugeXmlFile, saveAsLanguageXmlFile, StringComparison.OrdinalIgnoreCase))
{
- File.Copy(downloadLangaugeXmlFile, saveAsLanguageXmlFile, true);
+ _fileSystem.CopyFile(downloadLangaugeXmlFile, saveAsLanguageXmlFile, true);
}
await ExtractEpisodes(seriesDataPath, downloadLangaugeXmlFile, lastTvDbUpdateTime).ConfigureAwait(false);
@@ -268,9 +268,9 @@ namespace MediaBrowser.Providers.TV
{
var seriesDataPath = GetSeriesDataPath(_config.ApplicationPaths, seriesId);
- Directory.CreateDirectory(seriesDataPath);
+ _fileSystem.CreateDirectory(seriesDataPath);
- var files = new DirectoryInfo(seriesDataPath).EnumerateFiles("*.xml", SearchOption.TopDirectoryOnly)
+ var files = _fileSystem.GetFiles(seriesDataPath)
.ToList();
var seriesXmlFilename = preferredMetadataLanguage + ".xml";
@@ -1107,7 +1107,7 @@ namespace MediaBrowser.Providers.TV
var file = Path.Combine(seriesDataPath, string.Format("episode-{0}-{1}.xml", seasonNumber, episodeNumber));
// Only save the file if not already there, or if the episode has changed
- if (hasEpisodeChanged || !File.Exists(file))
+ if (hasEpisodeChanged || !_fileSystem.FileExists(file))
{
using (var writer = XmlWriter.Create(file, new XmlWriterSettings
{
@@ -1124,7 +1124,7 @@ namespace MediaBrowser.Providers.TV
file = Path.Combine(seriesDataPath, string.Format("episode-abs-{0}.xml", absoluteNumber));
// Only save the file if not already there, or if the episode has changed
- if (hasEpisodeChanged || !File.Exists(file))
+ if (hasEpisodeChanged || !_fileSystem.FileExists(file))
{
using (var writer = XmlWriter.Create(file, new XmlWriterSettings
{
@@ -1167,11 +1167,10 @@ namespace MediaBrowser.Providers.TV
{
try
{
- foreach (var file in new DirectoryInfo(path)
- .EnumerateFiles("*.xml", SearchOption.AllDirectories)
+ foreach (var file in _fileSystem.GetFilePaths(path, true)
.ToList())
{
- _fileSystem.DeleteFile(file.FullName);
+ _fileSystem.DeleteFile(file);
}
}
catch (DirectoryNotFoundException)
diff --git a/MediaBrowser.Providers/packages.config b/MediaBrowser.Providers/packages.config
index be21e92dc..fe2b571a4 100644
--- a/MediaBrowser.Providers/packages.config
+++ b/MediaBrowser.Providers/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
- <package id="morelinq" version="1.1.0" targetFramework="net45" />
+ <package id="morelinq" version="1.1.1" targetFramework="net45" />
<package id="taglib" version="2.1.0.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index f670176e6..d7209fbdf 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -31,7 +31,6 @@ namespace MediaBrowser.Server.Implementations.Channels
public class ChannelManager : IChannelManager, IDisposable
{
private IChannel[] _channels;
- private IChannelFactory[] _factories;
private readonly IUserManager _userManager;
private readonly IUserDataManager _userDataManager;
@@ -76,10 +75,9 @@ namespace MediaBrowser.Server.Implementations.Channels
}
}
- public void AddParts(IEnumerable<IChannel> channels, IEnumerable<IChannelFactory> factories)
+ public void AddParts(IEnumerable<IChannel> channels)
{
- _channels = channels.Where(i => !(i is IFactoryChannel)).ToArray();
- _factories = factories.ToArray();
+ _channels = channels.ToArray();
}
public string ChannelDownloadPath
@@ -99,20 +97,7 @@ namespace MediaBrowser.Server.Implementations.Channels
private IEnumerable<IChannel> GetAllChannels()
{
- return _factories
- .SelectMany(i =>
- {
- try
- {
- return i.GetChannels().ToList();
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error getting channel list", ex);
- return new List<IChannel>();
- }
- })
- .Concat(_channels)
+ return _channels
.OrderBy(i => i.Name);
}
@@ -318,7 +303,7 @@ namespace MediaBrowser.Server.Implementations.Channels
try
{
- var files = new DirectoryInfo(parentPath).EnumerateFiles("*", SearchOption.TopDirectoryOnly);
+ var files = _fileSystem.GetFiles(parentPath);
if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
{
@@ -411,7 +396,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{
_logger.Debug("Creating directory {0}", path);
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
fileInfo = new DirectoryInfo(path);
if (!fileInfo.Exists)
@@ -448,7 +433,7 @@ namespace MediaBrowser.Server.Implementations.Channels
item.Name = channelInfo.Name;
}
- await item.RefreshMetadata(new MetadataRefreshOptions
+ await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
{
ForceSave = isNew
@@ -1082,7 +1067,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{
try
{
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
_jsonSerializer.SerializeToFile(result, path);
}
@@ -1462,7 +1447,7 @@ namespace MediaBrowser.Server.Implementations.Channels
options.RequestHeaders[header.Key] = header.Value;
}
- Directory.CreateDirectory(Path.GetDirectoryName(destination));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(destination));
// Determine output extension
var response = await _httpClient.GetTempFileResponse(options).ConfigureAwait(false);
@@ -1500,7 +1485,7 @@ namespace MediaBrowser.Server.Implementations.Channels
throw new ApplicationException("Unexpected response type encountered: " + response.ContentType);
}
- File.Copy(response.TempFilePath, destination, true);
+ _fileSystem.CopyFile(response.TempFilePath, destination, true);
try
{
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
index 04f82db6f..b8c23224f 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
@@ -70,7 +70,7 @@ namespace MediaBrowser.Server.Implementations.Collections
try
{
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
var collection = new BoxSet
{
@@ -88,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.Collections
await parentFolder.AddChild(collection, CancellationToken.None).ConfigureAwait(false);
- await collection.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService()), CancellationToken.None)
+ await collection.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(_fileSystem)), CancellationToken.None)
.ConfigureAwait(false);
if (options.ItemIdList.Count > 0)
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs b/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs
index 915a27c11..0fc7fb3f6 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs
@@ -1,23 +1,26 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities;
using System.IO;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Collections
{
public class CollectionsDynamicFolder : IVirtualFolderCreator
{
private readonly IApplicationPaths _appPaths;
+ private IFileSystem _fileSystem;
- public CollectionsDynamicFolder(IApplicationPaths appPaths)
+ public CollectionsDynamicFolder(IApplicationPaths appPaths, IFileSystem fileSystem)
{
_appPaths = appPaths;
+ _fileSystem = fileSystem;
}
public BasePluginFolder GetFolder()
{
var path = Path.Combine(_appPaths.DataPath, "collections");
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
return new ManualCollectionsFolder
{
diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
index bf199503b..050b79db7 100644
--- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
+++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
@@ -15,6 +15,7 @@ using MediaBrowser.Model.Serialization;
using System;
using System.IO;
using System.Linq;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Configuration
{
@@ -23,15 +24,18 @@ namespace MediaBrowser.Server.Implementations.Configuration
/// </summary>
public class ServerConfigurationManager : BaseConfigurationManager, IServerConfigurationManager
{
+ private readonly IFileSystem _fileSystem;
+
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfigurationManager" /> class.
/// </summary>
/// <param name="applicationPaths">The application paths.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="xmlSerializer">The XML serializer.</param>
- public ServerConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer)
+ public ServerConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer, IFileSystem fileSystem)
: base(applicationPaths, logManager, xmlSerializer)
{
+ _fileSystem = fileSystem;
UpdateItemsByNamePath();
UpdateMetadataPath();
}
@@ -198,7 +202,7 @@ namespace MediaBrowser.Server.Implementations.Configuration
&& !string.Equals(Configuration.ItemsByNamePath ?? string.Empty, newPath))
{
// Validate
- if (!Directory.Exists(newPath))
+ if (!_fileSystem.DirectoryExists(newPath))
{
throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
}
@@ -218,7 +222,7 @@ namespace MediaBrowser.Server.Implementations.Configuration
&& !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath))
{
// Validate
- if (!Directory.Exists(newPath))
+ if (!_fileSystem.DirectoryExists(newPath))
{
throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
}
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
index 8a659fb65..a8900fa5b 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
@@ -10,6 +10,7 @@ using System.IO;
using System.Net;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Connect
{
@@ -23,8 +24,9 @@ namespace MediaBrowser.Server.Implementations.Connect
private readonly INetworkManager _networkManager;
private readonly IApplicationHost _appHost;
+ private readonly IFileSystem _fileSystem;
- public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost)
+ public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager, IApplicationHost appHost, IFileSystem fileSystem)
{
_httpClient = httpClient;
_appPaths = appPaths;
@@ -32,6 +34,7 @@ namespace MediaBrowser.Server.Implementations.Connect
_networkManager = networkManager;
_connectManager = connectManager;
_appHost = appHost;
+ _fileSystem = fileSystem;
}
public void Run()
@@ -90,8 +93,8 @@ namespace MediaBrowser.Server.Implementations.Connect
try
{
- Directory.CreateDirectory(Path.GetDirectoryName(path));
- File.WriteAllText(path, address, Encoding.UTF8);
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.WriteAllText(path, address, Encoding.UTF8);
}
catch (Exception ex)
{
@@ -105,7 +108,7 @@ namespace MediaBrowser.Server.Implementations.Connect
try
{
- var endpoint = File.ReadAllText(path, Encoding.UTF8);
+ var endpoint = _fileSystem.ReadAllText(path, Encoding.UTF8);
if (IsValid(endpoint))
{
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
index 7cd96c5f3..aab3a2121 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
@@ -23,6 +23,7 @@ using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Connect
{
@@ -40,6 +41,7 @@ namespace MediaBrowser.Server.Implementations.Connect
private readonly IUserManager _userManager;
private readonly IProviderManager _providerManager;
private readonly ISecurityManager _securityManager;
+ private readonly IFileSystem _fileSystem;
private ConnectData _data = new ConnectData();
@@ -104,7 +106,7 @@ namespace MediaBrowser.Server.Implementations.Connect
IEncryptionManager encryption,
IHttpClient httpClient,
IServerApplicationHost appHost,
- IServerConfigurationManager config, IUserManager userManager, IProviderManager providerManager, ISecurityManager securityManager)
+ IServerConfigurationManager config, IUserManager userManager, IProviderManager providerManager, ISecurityManager securityManager, IFileSystem fileSystem)
{
_logger = logger;
_appPaths = appPaths;
@@ -116,6 +118,7 @@ namespace MediaBrowser.Server.Implementations.Connect
_userManager = userManager;
_providerManager = providerManager;
_securityManager = securityManager;
+ _fileSystem = fileSystem;
_userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated;
_config.ConfigurationUpdated += _config_ConfigurationUpdated;
@@ -315,7 +318,7 @@ namespace MediaBrowser.Server.Implementations.Connect
try
{
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
var json = _json.SerializeToString(_data);
@@ -323,7 +326,7 @@ namespace MediaBrowser.Server.Implementations.Connect
lock (_dataFileLock)
{
- File.WriteAllText(path, encrypted, Encoding.UTF8);
+ _fileSystem.WriteAllText(path, encrypted, Encoding.UTF8);
}
}
catch (Exception ex)
@@ -340,7 +343,7 @@ namespace MediaBrowser.Server.Implementations.Connect
{
lock (_dataFileLock)
{
- var encrypted = File.ReadAllText(path, Encoding.UTF8);
+ var encrypted = _fileSystem.ReadAllText(path, Encoding.UTF8);
var json = _encryption.DecryptString(encrypted);
@@ -943,7 +946,7 @@ namespace MediaBrowser.Server.Implementations.Connect
{
await _providerManager.SaveImage(user, imageUrl, _connectImageSemaphore, ImageType.Primary, null, CancellationToken.None).ConfigureAwait(false);
- await user.RefreshMetadata(new MetadataRefreshOptions
+ await user.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
{
ForceSave = true,
diff --git a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs
index 566f4c5f4..15567703d 100644
--- a/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Devices/CameraUploadsFolder.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities;
using System;
using System.IO;
using System.Linq;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Devices
{
@@ -51,17 +52,19 @@ namespace MediaBrowser.Server.Implementations.Devices
public class CameraUploadsDynamicFolder : IVirtualFolderCreator
{
private readonly IApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
- public CameraUploadsDynamicFolder(IApplicationPaths appPaths)
+ public CameraUploadsDynamicFolder(IApplicationPaths appPaths, IFileSystem fileSystem)
{
_appPaths = appPaths;
+ _fileSystem = fileSystem;
}
public BasePluginFolder GetFolder()
{
var path = Path.Combine(_appPaths.DataPath, "camerauploads");
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
return new CameraUploadsFolder
{
diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs
index 04337dda6..a6a8b3a7a 100644
--- a/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs
+++ b/MediaBrowser.Server.Implementations/Devices/DeviceManager.cs
@@ -8,6 +8,7 @@ using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Session;
using MediaBrowser.Model.Users;
@@ -151,12 +152,13 @@ namespace MediaBrowser.Server.Implementations.Devices
path = Path.Combine(path, _fileSystem.GetValidFilename(file.Album));
}
- Directory.CreateDirectory(path);
-
path = Path.Combine(path, file.Name);
+ path = Path.ChangeExtension(path, MimeTypes.ToExtension(file.MimeType) ?? "jpg");
_libraryMonitor.ReportFileSystemChangeBeginning(path);
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+
try
{
using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs b/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs
index 6d324b1ab..b8262d05f 100644
--- a/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs
+++ b/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs
@@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Devices
public Task SaveDevice(DeviceInfo device)
{
var path = Path.Combine(GetDevicePath(device.Id), "device.json");
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
lock (_syncLock)
{
@@ -178,7 +178,7 @@ namespace MediaBrowser.Server.Implementations.Devices
public void AddCameraUpload(string deviceId, LocalFileInfo file)
{
var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
lock (_syncLock)
{
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index edfef38fd..2f2ebb349 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -908,12 +908,6 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.DisplayMediaType = item.DisplayMediaType;
}
- // Leave null if false
- if (item.IsUnidentified)
- {
- dto.IsUnidentified = item.IsUnidentified;
- }
-
if (fields.Contains(ItemFields.Settings))
{
dto.LockedFields = item.LockedFields;
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
index d5b7f5b36..932e94b2a 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
@@ -60,7 +60,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
{
var dataPath = Path.Combine(_appPaths.DataPath, "remotenotifications.json");
- var lastRunTime = File.Exists(dataPath) ? _fileSystem.GetLastWriteTimeUtc(dataPath) : DateTime.MinValue;
+ var lastRunTime = _fileSystem.FileExists(dataPath) ? _fileSystem.GetLastWriteTimeUtc(dataPath) : DateTime.MinValue;
try
{
@@ -88,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
{
var notifications = _json.DeserializeFromStream<RemoteNotification[]>(stream);
- File.WriteAllText(dataPath, string.Empty);
+ _fileSystem.WriteAllText(dataPath, string.Empty);
await CreateNotifications(notifications, lastRunTime).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
index 06b72e4ef..0389980e2 100644
--- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
+++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
@@ -182,7 +182,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_logger.Info("Sorting file {0} to new path {1}", sourcePath, newPath);
result.TargetPath = newPath;
- var fileExists = File.Exists(result.TargetPath);
+ var fileExists = _fileSystem.FileExists(result.TargetPath);
var otherDuplicatePaths = GetOtherDuplicatePaths(result.TargetPath, series, seasonNumber, episodeNumber, endingEpiosdeNumber);
if (!overwriteExisting)
@@ -272,7 +272,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var destination = Path.Combine(directory, filename);
- File.Move(file, destination);
+ _fileSystem.MoveFile(file, destination);
}
}
}
@@ -332,19 +332,19 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
_libraryMonitor.ReportFileSystemChangeBeginning(result.TargetPath);
- Directory.CreateDirectory(Path.GetDirectoryName(result.TargetPath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(result.TargetPath));
- var targetAlreadyExists = File.Exists(result.TargetPath);
+ var targetAlreadyExists = _fileSystem.FileExists(result.TargetPath);
try
{
if (targetAlreadyExists || options.CopyOriginalFile)
{
- File.Copy(result.OriginalPath, result.TargetPath, true);
+ _fileSystem.CopyFile(result.OriginalPath, result.TargetPath, true);
}
else
{
- File.Move(result.OriginalPath, result.TargetPath);
+ _fileSystem.MoveFile(result.OriginalPath, result.TargetPath);
}
result.Status = FileSortingStatus.Success;
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs
index 0caa8c26e..2867cbecb 100644
--- a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs
+++ b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs
@@ -111,8 +111,8 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
try
{
- return Directory
- .EnumerateDirectories(path, "*", SearchOption.TopDirectoryOnly)
+ return _fileSystem
+ .GetFileSystemEntryPaths(path)
.ToList();
}
catch (IOException ex)
@@ -132,8 +132,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
try
{
- return new DirectoryInfo(path)
- .EnumerateFiles("*", SearchOption.AllDirectories)
+ return _fileSystem.GetFiles(path, true)
.ToList();
}
catch (IOException ex)
@@ -151,8 +150,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
/// <param name="extensions">The extensions.</param>
private void DeleteLeftOverFiles(string path, IEnumerable<string> extensions)
{
- var eligibleFiles = new DirectoryInfo(path)
- .EnumerateFiles("*", SearchOption.AllDirectories)
+ var eligibleFiles = _fileSystem.GetFiles(path, true)
.Where(i => extensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
.ToList();
@@ -189,7 +187,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
try
{
_logger.Debug("Deleting empty directory {0}", path);
- Directory.Delete(path);
+ _fileSystem.DeleteDirectory(path, false);
}
catch (UnauthorizedAccessException) { }
catch (DirectoryNotFoundException) { }
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
index 3795f4b15..1885afc61 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -79,6 +79,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
_containerAdapter = new ContainerAdapter(applicationHost);
}
+ public string GlobalResponse { get; set; }
+
public override void Configure(Container container)
{
HostConfig.Instance.DefaultRedirectPath = DefaultRedirectPath;
@@ -336,6 +338,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return Task.FromResult(true);
}
+ if (!string.IsNullOrWhiteSpace(GlobalResponse))
+ {
+ httpRes.Write(GlobalResponse);
+ httpRes.ContentType = "text/plain";
+ return Task.FromResult(true);
+ }
+
var handler = HttpHandlerFactory.GetHandler(httpReq);
var remoteIp = httpReq.RemoteIp;
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
index 80892b96c..ae5ce796e 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
@@ -69,47 +69,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
token = httpReq.QueryString["api_key"];
}
- // Hack until iOS is updated
- // TODO: Remove
- if (string.IsNullOrWhiteSpace(client))
- {
- var userAgent = httpReq.Headers["User-Agent"] ?? string.Empty;
-
- if (userAgent.IndexOf("mediabrowserios", StringComparison.OrdinalIgnoreCase) != -1 ||
- userAgent.IndexOf("iphone", StringComparison.OrdinalIgnoreCase) != -1 ||
- userAgent.IndexOf("ipad", StringComparison.OrdinalIgnoreCase) != -1)
- {
- client = "iOS";
- }
-
- else if (userAgent.IndexOf("crKey", StringComparison.OrdinalIgnoreCase) != -1)
- {
- client = "Chromecast";
- }
- }
-
- // Hack until iOS is updated
- // TODO: Remove
- if (string.IsNullOrWhiteSpace(device))
- {
- var userAgent = httpReq.Headers["User-Agent"] ?? string.Empty;
-
- if (userAgent.IndexOf("iPhone", StringComparison.OrdinalIgnoreCase) != -1)
- {
- device = "iPhone";
- }
-
- else if (userAgent.IndexOf("iPad", StringComparison.OrdinalIgnoreCase) != -1)
- {
- device = "iPad";
- }
-
- else if (userAgent.IndexOf("crKey", StringComparison.OrdinalIgnoreCase) != -1)
- {
- device = "Chromecast";
- }
- }
-
var info = new AuthorizationInfo
{
Client = client,
diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
index 5bd26ce18..cb9d5a09f 100644
--- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
+++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
@@ -645,7 +645,7 @@ namespace MediaBrowser.Server.Implementations.IO
if (item != null)
{
// If the item has been deleted find the first valid parent that still exists
- while (!Directory.Exists(item.Path) && !File.Exists(item.Path))
+ while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path))
{
item = item.Parent;
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index cc9d9551c..26961c490 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -395,12 +395,12 @@ namespace MediaBrowser.Server.Implementations.Library
{
foreach (var path in item.GetDeletePaths().ToList())
{
- if (Directory.Exists(path))
+ if (_fileSystem.DirectoryExists(path))
{
_logger.Debug("Deleting path {0}", path);
_fileSystem.DeleteDirectory(path, true);
}
- else if (File.Exists(path))
+ else if (_fileSystem.FileExists(path))
{
_logger.Debug("Deleting path {0}", path);
_fileSystem.DeleteFile(path);
@@ -548,7 +548,7 @@ namespace MediaBrowser.Server.Implementations.Library
public BaseItem ResolvePath(FileSystemInfo fileInfo,
Folder parent = null)
{
- return ResolvePath(fileInfo, new DirectoryService(_logger), parent);
+ return ResolvePath(fileInfo, new DirectoryService(_logger, _fileSystem), parent);
}
private BaseItem ResolvePath(FileSystemInfo fileInfo, IDirectoryService directoryService, Folder parent = null, string collectionType = null)
@@ -691,7 +691,7 @@ namespace MediaBrowser.Server.Implementations.Library
{
var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath;
- Directory.CreateDirectory(rootFolderPath);
+ _fileSystem.CreateDirectory(rootFolderPath);
var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(new DirectoryInfo(rootFolderPath));
@@ -742,7 +742,7 @@ namespace MediaBrowser.Server.Implementations.Library
{
var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath;
- Directory.CreateDirectory(userRootPath);
+ _fileSystem.CreateDirectory(userRootPath);
var tmpItem = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder;
@@ -1007,9 +1007,9 @@ namespace MediaBrowser.Server.Implementations.Library
public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
{
// Ensure the location is available.
- Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
+ _fileSystem.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
- return new PeopleValidator(this, _logger, ConfigurationManager).ValidatePeople(cancellationToken, progress);
+ return new PeopleValidator(this, _logger, ConfigurationManager, _fileSystem).ValidatePeople(cancellationToken, progress);
}
/// <summary>
@@ -1064,7 +1064,7 @@ namespace MediaBrowser.Server.Implementations.Library
progress.Report(.5);
// Start by just validating the children of the root, but go no further
- await RootFolder.ValidateChildren(new Progress<double>(), cancellationToken, new MetadataRefreshOptions(), recursive: false);
+ await RootFolder.ValidateChildren(new Progress<double>(), cancellationToken, new MetadataRefreshOptions(_fileSystem), recursive: false);
progress.Report(1);
@@ -1072,7 +1072,7 @@ namespace MediaBrowser.Server.Implementations.Library
await userRoot.RefreshMetadata(cancellationToken).ConfigureAwait(false);
- await userRoot.ValidateChildren(new Progress<double>(), cancellationToken, new MetadataRefreshOptions(), recursive: false).ConfigureAwait(false);
+ await userRoot.ValidateChildren(new Progress<double>(), cancellationToken, new MetadataRefreshOptions(_fileSystem), recursive: false).ConfigureAwait(false);
progress.Report(2);
var innerProgress = new ActionableProgress<double>();
@@ -1080,7 +1080,7 @@ namespace MediaBrowser.Server.Implementations.Library
innerProgress.RegisterAction(pct => progress.Report(2 + pct * .73));
// Now validate the entire media library
- await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(), recursive: true).ConfigureAwait(false);
+ await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(_fileSystem), recursive: true).ConfigureAwait(false);
progress.Report(75);
@@ -1165,7 +1165,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>IEnumerable{VirtualFolderInfo}.</returns>
private IEnumerable<VirtualFolderInfo> GetView(string path)
{
- return Directory.EnumerateDirectories(path, "*", SearchOption.TopDirectoryOnly)
+ return _fileSystem.GetFileSystemEntryPaths(path)
.Select(dir => new VirtualFolderInfo
{
Name = Path.GetFileName(dir),
@@ -1638,6 +1638,7 @@ namespace MediaBrowser.Server.Implementations.Library
}
private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromHours(24);
+ //private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromMinutes(1);
public Task<UserView> GetNamedView(User user,
string name,
@@ -1645,12 +1646,7 @@ namespace MediaBrowser.Server.Implementations.Library
string sortName,
CancellationToken cancellationToken)
{
- if (ConfigurationManager.Configuration.EnableUserSpecificUserViews)
- {
- return GetNamedViewInternal(user, name, null, viewType, sortName, null, cancellationToken);
- }
-
- return GetNamedView(name, viewType, sortName, cancellationToken);
+ return GetNamedViewInternal(user, name, null, viewType, sortName, null, cancellationToken);
}
public async Task<UserView> GetNamedView(string name,
@@ -1671,7 +1667,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (item == null ||
!string.Equals(item.Path, path, StringComparison.OrdinalIgnoreCase))
{
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
item = new UserView
{
@@ -1702,7 +1698,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (refresh)
{
await item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None).ConfigureAwait(false);
- _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions
+ _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem)
{
// Not sure why this is necessary but need to figure it out
// View images are not getting utilized without this
@@ -1758,7 +1754,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (item == null)
{
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
item = new UserView
{
@@ -1767,7 +1763,8 @@ namespace MediaBrowser.Server.Implementations.Library
DateCreated = DateTime.UtcNow,
Name = name,
ViewType = viewType,
- ForcedSortName = sortName
+ ForcedSortName = sortName,
+ UserId = user.Id
};
if (!string.IsNullOrWhiteSpace(parentId))
@@ -1780,6 +1777,12 @@ namespace MediaBrowser.Server.Implementations.Library
isNew = true;
}
+ if (!item.UserId.HasValue)
+ {
+ item.UserId = user.Id;
+ await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
+ }
+
if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase))
{
item.ViewType = viewType;
@@ -1790,7 +1793,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (refresh)
{
- _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions
+ _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem)
{
// Need to force save to increment DateLastSaved
ForceSave = true
@@ -1828,7 +1831,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (item == null)
{
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
item = new UserView
{
@@ -1860,7 +1863,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (refresh)
{
- _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions
+ _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem)
{
// Need to force save to increment DateLastSaved
ForceSave = true
@@ -2181,7 +2184,7 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
- return item.People ?? new List<PersonInfo>();
+ return new List<PersonInfo>();
}
public List<Person> GetPeopleItems(InternalPeopleQuery query)
diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
index e3ec99392..a348c728e 100644
--- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
@@ -15,6 +15,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Library
{
@@ -24,17 +25,19 @@ namespace MediaBrowser.Server.Implementations.Library
private readonly IUserManager _userManager;
private readonly ILibraryManager _libraryManager;
private readonly IJsonSerializer _jsonSerializer;
+ private readonly IFileSystem _fileSystem;
private IMediaSourceProvider[] _providers;
private readonly ILogger _logger;
- public MediaSourceManager(IItemRepository itemRepo, IUserManager userManager, ILibraryManager libraryManager, ILogger logger, IJsonSerializer jsonSerializer)
+ public MediaSourceManager(IItemRepository itemRepo, IUserManager userManager, ILibraryManager libraryManager, ILogger logger, IJsonSerializer jsonSerializer, IFileSystem fileSystem)
{
_itemRepo = itemRepo;
_userManager = userManager;
_libraryManager = libraryManager;
_logger = logger;
_jsonSerializer = jsonSerializer;
+ _fileSystem = fileSystem;
}
public void AddParts(IEnumerable<IMediaSourceProvider> providers)
@@ -127,9 +130,12 @@ namespace MediaBrowser.Server.Implementations.Library
{
var supportsExternalStream = StreamSupportsExternalStream(subStream);
- if (supportsExternalStream && videoBitrate >= maxAllowedBitrateForExternalSubtitleStream)
+ if (!subStream.IsExternal)
{
- supportsExternalStream = false;
+ if (supportsExternalStream && videoBitrate >= maxAllowedBitrateForExternalSubtitleStream)
+ {
+ supportsExternalStream = false;
+ }
}
subStream.SupportsExternalStream = supportsExternalStream;
@@ -167,7 +173,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (source.Protocol == MediaProtocol.File)
{
// TODO: Path substitution
- if (!File.Exists(source.Path))
+ if (!_fileSystem.FileExists(source.Path))
{
source.SupportsDirectStream = false;
}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 0d1e4202c..d9f23977c 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -309,20 +309,26 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
//we need to only look at the name of this actual item (not parents)
var justName = item.IsInMixedFolder ? Path.GetFileName(item.Path) : Path.GetFileName(item.ContainingFolderPath);
- // check for tmdb id
- var tmdbid = justName.GetAttributeValue("tmdbid");
-
- if (!string.IsNullOrEmpty(tmdbid))
+ if (!string.IsNullOrWhiteSpace(justName))
{
- item.SetProviderId(MetadataProviders.Tmdb, tmdbid);
- }
+ // check for tmdb id
+ var tmdbid = justName.GetAttributeValue("tmdbid");
- // check for imdb id - we use full media path, as we can assume, that this will match in any use case (wither id in parent dir or in file name)
- var imdbid = item.Path.GetAttributeValue("imdbid");
+ if (!string.IsNullOrWhiteSpace(tmdbid))
+ {
+ item.SetProviderId(MetadataProviders.Tmdb, tmdbid);
+ }
+ }
- if (!string.IsNullOrEmpty(imdbid))
+ if (!string.IsNullOrWhiteSpace(item.Path))
{
- item.SetProviderId(MetadataProviders.Imdb, imdbid);
+ // check for imdb id - we use full media path, as we can assume, that this will match in any use case (wither id in parent dir or in file name)
+ var imdbid = item.Path.GetAttributeValue("imdbid");
+
+ if (!string.IsNullOrWhiteSpace(imdbid))
+ {
+ item.SetProviderId(MetadataProviders.Imdb, imdbid);
+ }
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs
index 5012f2479..a8fc7b4aa 100644
--- a/MediaBrowser.Server.Implementations/Library/UserManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs
@@ -454,7 +454,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <returns>Task.</returns>
public Task RefreshUsersMetadata(CancellationToken cancellationToken)
{
- var tasks = Users.Select(user => user.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken)).ToList();
+ var tasks = Users.Select(user => user.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken)).ToList();
return Task.WhenAll(tasks);
}
@@ -745,7 +745,7 @@ namespace MediaBrowser.Server.Implementations.Library
text.AppendLine(string.Empty);
text.AppendLine("The pin code will expire at " + expiration.ToLocalTime().ToShortDateString() + " " + expiration.ToLocalTime().ToShortTimeString());
- File.WriteAllText(path, text.ToString(), Encoding.UTF8);
+ _fileSystem.WriteAllText(path, text.ToString(), Encoding.UTF8);
var result = new PasswordPinCreationResult
{
@@ -919,7 +919,7 @@ namespace MediaBrowser.Server.Implementations.Library
var path = GetPolifyFilePath(user);
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
lock (_policySyncLock)
{
@@ -1006,7 +1006,7 @@ namespace MediaBrowser.Server.Implementations.Library
config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json);
}
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
lock (_configSyncLock)
{
diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
index 43f77ec49..fe9e09318 100644
--- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
@@ -65,20 +65,24 @@ namespace MediaBrowser.Server.Implementations.Library
var list = new List<Folder>();
- if (_config.Configuration.EnableUserSpecificUserViews)
+ if (_config.Configuration.EnableUserViews)
{
foreach (var folder in standaloneFolders)
{
var collectionFolder = folder as ICollectionFolder;
var folderViewType = collectionFolder == null ? null : collectionFolder.CollectionType;
- if (plainFolderIds.Contains(folder.Id))
+ if (UserView.IsUserSpecific(folder))
{
- list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, false, string.Empty, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false));
+ }
+ else if (plainFolderIds.Contains(folder.Id))
+ {
+ list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, false, string.Empty, cancellationToken).ConfigureAwait(false));
}
else if (!string.IsNullOrWhiteSpace(folderViewType))
{
- list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, cancellationToken).ConfigureAwait(false));
}
else
{
@@ -88,7 +92,29 @@ namespace MediaBrowser.Server.Implementations.Library
}
else
{
- list.AddRange(standaloneFolders);
+ // TODO: Deprecate this whole block
+ foreach (var folder in standaloneFolders)
+ {
+ var collectionFolder = folder as ICollectionFolder;
+ var folderViewType = collectionFolder == null ? null : collectionFolder.CollectionType;
+
+ if (UserView.IsUserSpecific(folder))
+ {
+ list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false));
+ }
+ else if (plainFolderIds.Contains(folder.Id))
+ {
+ list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, false, string.Empty, user, cancellationToken).ConfigureAwait(false));
+ }
+ else if (!string.IsNullOrWhiteSpace(folderViewType))
+ {
+ list.Add(await GetUserView(folder.Id, folder.Name, folderViewType, true, string.Empty, user, cancellationToken).ConfigureAwait(false));
+ }
+ else
+ {
+ list.Add(folder);
+ }
+ }
}
var parents = foldersWithViewTypes.Where(i => string.Equals(i.GetViewType(user), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(i.GetViewType(user)))
@@ -123,22 +149,6 @@ namespace MediaBrowser.Server.Implementations.Library
list.Add(await GetUserView(parents, list, CollectionType.Games, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
- parents = foldersWithViewTypes.Where(i => string.Equals(i.GetViewType(user), CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
- .ToList();
-
- if (parents.Count > 0)
- {
- list.Add(await GetUserView(parents, list, CollectionType.BoxSets, string.Empty, user, cancellationToken).ConfigureAwait(false));
- }
-
- parents = foldersWithViewTypes.Where(i => string.Equals(i.GetViewType(user), CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
- .ToList();
-
- if (parents.Count > 0)
- {
- list.Add(await GetUserView(parents, list, CollectionType.Playlists, string.Empty, user, cancellationToken).ConfigureAwait(false));
- }
-
if (user.Configuration.DisplayFoldersView)
{
var name = _localizationManager.GetLocalizedString("ViewType" + CollectionType.Folders);
@@ -204,9 +214,9 @@ namespace MediaBrowser.Server.Implementations.Library
public async Task<UserView> GetUserView(List<ICollectionFolder> parents, List<Folder> currentViews, string viewType, string sortName, User user, CancellationToken cancellationToken)
{
var name = _localizationManager.GetLocalizedString("ViewType" + viewType);
- var enableUserSpecificViews = _config.Configuration.EnableUserSpecificUserViews;
+ var enableUserViews = _config.Configuration.EnableUserViews;
- if (parents.Count == 1 && parents.All(i => string.Equals((enableUserSpecificViews ? i.CollectionType : i.GetViewType(user)), viewType, StringComparison.OrdinalIgnoreCase)))
+ if (parents.Count == 1 && parents.All(i => string.Equals((enableUserViews ? i.GetViewType(user) : i.CollectionType), viewType, StringComparison.OrdinalIgnoreCase)))
{
if (!string.IsNullOrWhiteSpace(parents[0].Name))
{
@@ -222,7 +232,7 @@ namespace MediaBrowser.Server.Implementations.Library
return await GetUserView(parentId, name, viewType, enableRichView, sortName, user, cancellationToken).ConfigureAwait(false);
}
- if (enableUserSpecificViews)
+ if (!enableUserViews)
{
var view = await _libraryManager.GetNamedView(user, name, viewType, sortName, cancellationToken).ConfigureAwait(false);
@@ -244,6 +254,12 @@ namespace MediaBrowser.Server.Implementations.Library
return _libraryManager.GetNamedView(user, name, parentId.ToString("N"), viewType, sortName, null, cancellationToken);
}
+ public Task<UserView> GetUserView(Guid parentId, string name, string viewType, bool enableRichView, string sortName, CancellationToken cancellationToken)
+ {
+ viewType = enableRichView ? viewType : null;
+ return _libraryManager.GetNamedView(name, parentId.ToString("N"), viewType, sortName, null, cancellationToken);
+ }
+
public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request)
{
var user = _userManager.GetUserById(request.UserId);
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs
index a4c43af5d..c6b294e83 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs
@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Library.Validators
{
@@ -29,17 +30,19 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
private readonly ILogger _logger;
private readonly IServerConfigurationManager _config;
+ private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="PeopleValidator" /> class.
/// </summary>
/// <param name="libraryManager">The library manager.</param>
/// <param name="logger">The logger.</param>
- public PeopleValidator(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config)
+ public PeopleValidator(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
_logger = logger;
_config = config;
+ _fileSystem = fileSystem;
}
private bool DownloadMetadata(PersonInfo i, PeopleMetadataOptions options)
@@ -121,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
validIds.Add(item.Id);
- var options = new MetadataRefreshOptions
+ var options = new MetadataRefreshOptions(_fileSystem)
{
MetadataRefreshMode = person.Value ? MetadataRefreshMode.Default : MetadataRefreshMode.ValidationOnly,
ImageRefreshMode = person.Value ? ImageRefreshMode.Default : ImageRefreshMode.ValidationOnly
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 4e0d6e8d4..38b83eb02 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -8,7 +8,9 @@ using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Events;
@@ -47,10 +49,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
private readonly ILibraryManager _libraryManager;
private readonly IProviderManager _providerManager;
private readonly IFileOrganizationService _organizationService;
+ private readonly IMediaEncoder _mediaEncoder;
public static EmbyTV Current;
- public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ISecurityManager security, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService)
+ public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ISecurityManager security, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder)
{
Current = this;
@@ -64,12 +67,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_libraryMonitor = libraryMonitor;
_providerManager = providerManager;
_organizationService = organizationService;
+ _mediaEncoder = mediaEncoder;
_liveTvManager = (LiveTvManager)liveTvManager;
_jsonSerializer = jsonSerializer;
- _recordingProvider = new ItemDataProvider<RecordingInfo>(jsonSerializer, _logger, Path.Combine(DataPath, "recordings"), (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase));
- _seriesTimerProvider = new SeriesTimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers"));
- _timerProvider = new TimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "timers"));
+ _recordingProvider = new ItemDataProvider<RecordingInfo>(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "recordings"), (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase));
+ _seriesTimerProvider = new SeriesTimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers"));
+ _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"));
_timerProvider.TimerFired += _timerProvider_TimerFired;
}
@@ -126,6 +130,33 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return status;
}
+ public async Task RefreshSeriesTimers(CancellationToken cancellationToken, IProgress<double> progress)
+ {
+ var timers = await GetSeriesTimersAsync(cancellationToken).ConfigureAwait(false);
+
+ List<ChannelInfo> channels = null;
+
+ foreach (var timer in timers)
+ {
+ List<ProgramInfo> epgData;
+
+ if (timer.RecordAnyChannel)
+ {
+ if (channels == null)
+ {
+ channels = (await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false)).ToList();
+ }
+ var channelIds = channels.Select(i => i.Id).ToList();
+ epgData = GetEpgDataForChannels(channelIds);
+ }
+ else
+ {
+ epgData = GetEpgDataForChannel(timer.ChannelId);
+ }
+ await UpdateTimersForSeriesTimer(epgData, timer).ConfigureAwait(false);
+ }
+ }
+
private List<ChannelInfo> _channelCache = null;
private async Task<IEnumerable<ChannelInfo>> GetChannelsAsync(bool enableCache, CancellationToken cancellationToken)
{
@@ -235,7 +266,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
try
{
- File.Delete(remove.Path);
+ _fileSystem.DeleteFile(remove.Path);
}
catch (DirectoryNotFoundException)
{
@@ -366,6 +397,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
{
+ try
+ {
+ return await GetProgramsAsyncInternal(channelId, startDateUtc, endDateUtc, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting programs", ex);
+ return GetEpgDataForChannel(channelId).Where(i => i.StartDate <= endDateUtc && i.EndDate >= startDateUtc);
+ }
+ }
+
+ private async Task<IEnumerable<ProgramInfo>> GetProgramsAsyncInternal(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken)
+ {
var channels = await GetChannelsAsync(true, cancellationToken).ConfigureAwait(false);
var channel = channels.First(i => string.Equals(i.Id, channelId, StringComparison.OrdinalIgnoreCase));
@@ -373,6 +417,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
var programs = await provider.Item1.GetProgramsAsync(provider.Item2, channel.Number, startDateUtc, endDateUtc, cancellationToken)
.ConfigureAwait(false);
+
var list = programs.ToList();
// Replace the value that came from the provider with a normalized value
@@ -428,6 +473,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
if (mediaSourceInfo != null)
{
+ await AddMediaInfo(mediaSourceInfo, false, cancellationToken).ConfigureAwait(false);
+
mediaSourceInfo.Id = Guid.NewGuid().ToString("N");
return mediaSourceInfo;
}
@@ -458,6 +505,84 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
throw new NotImplementedException();
}
+ private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
+ {
+ var originalRuntime = mediaSource.RunTimeTicks;
+
+ var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
+ {
+ InputPath = mediaSource.Path,
+ Protocol = mediaSource.Protocol,
+ MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
+ ExtractChapters = false
+
+ }, cancellationToken).ConfigureAwait(false);
+
+ mediaSource.Bitrate = info.Bitrate;
+ mediaSource.Container = info.Container;
+ mediaSource.Formats = info.Formats;
+ mediaSource.MediaStreams = info.MediaStreams;
+ mediaSource.RunTimeTicks = info.RunTimeTicks;
+ mediaSource.Size = info.Size;
+ mediaSource.Timestamp = info.Timestamp;
+ mediaSource.Video3DFormat = info.Video3DFormat;
+ mediaSource.VideoType = info.VideoType;
+
+ mediaSource.DefaultSubtitleStreamIndex = null;
+
+ // Null this out so that it will be treated like a live stream
+ if (!originalRuntime.HasValue)
+ {
+ mediaSource.RunTimeTicks = null;
+ }
+
+ var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
+
+ if (audioStream == null || audioStream.Index == -1)
+ {
+ mediaSource.DefaultAudioStreamIndex = null;
+ }
+ else
+ {
+ mediaSource.DefaultAudioStreamIndex = audioStream.Index;
+ }
+
+ var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video);
+ if (videoStream != null)
+ {
+ if (!videoStream.BitRate.HasValue)
+ {
+ var width = videoStream.Width ?? 1920;
+
+ if (width >= 1900)
+ {
+ videoStream.BitRate = 8000000;
+ }
+
+ else if (width >= 1260)
+ {
+ videoStream.BitRate = 3000000;
+ }
+
+ else if (width >= 700)
+ {
+ videoStream.BitRate = 1000000;
+ }
+ }
+ }
+
+ // Try to estimate this
+ if (!mediaSource.Bitrate.HasValue)
+ {
+ var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
+
+ if (total > 0)
+ {
+ mediaSource.Bitrate = total;
+ }
+ }
+ }
+
public Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken)
{
throw new NotImplementedException();
@@ -500,14 +625,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
catch (Exception ex)
{
_logger.ErrorException("Error recording stream", ex);
-
- if (DateTime.UtcNow < timer.EndDate)
- {
- const int retryIntervalSeconds = 60;
- _logger.Info("Retrying recording in {0} seconds.", retryIntervalSeconds);
-
- _timerProvider.StartTimer(timer, TimeSpan.FromSeconds(retryIntervalSeconds));
- }
}
}
@@ -553,7 +670,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
var recordingFileName = _fileSystem.GetValidFilename(RecordingHelper.GetRecordingName(timer, info)) + ".ts";
recordPath = Path.Combine(recordPath, recordingFileName);
- Directory.CreateDirectory(Path.GetDirectoryName(recordPath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath));
var recording = _recordingProvider.GetAll().FirstOrDefault(x => string.Equals(x.ProgramId, info.Id, StringComparison.OrdinalIgnoreCase));
@@ -597,7 +714,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_recordingProvider.Update(recording);
_logger.Info("Beginning recording.");
-
+
try
{
httpRequestOptions.BufferContent = false;
@@ -607,7 +724,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_logger.Info("Writing file to path: " + recordPath);
using (var response = await _httpClient.SendAsync(httpRequestOptions, "GET"))
{
- using (var output = File.Open(recordPath, FileMode.Create, FileAccess.Write, FileShare.Read))
+ using (var output = _fileSystem.GetFileStream(recordPath, FileMode.Create, FileAccess.Write, FileShare.Read))
{
await response.Content.CopyToAsync(output, StreamDefaults.DefaultCopyToBufferSize, linkedToken);
}
@@ -626,15 +743,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_logger.ErrorException("Error recording", ex);
recording.Status = RecordingStatus.Error;
}
+ finally
+ {
+ CancellationTokenSource removed;
+ _activeRecordings.TryRemove(timer.Id, out removed);
+ }
recording.DateLastUpdated = DateTime.UtcNow;
_recordingProvider.Update(recording);
- _timerProvider.Delete(timer);
- _logger.Info("Recording was a success");
if (recording.Status == RecordingStatus.Completed)
{
OnSuccessfulRecording(recording);
+ _timerProvider.Delete(timer);
+ }
+ else if (DateTime.UtcNow < timer.EndDate)
+ {
+ const int retryIntervalSeconds = 60;
+ _logger.Info("Retrying recording in {0} seconds.", retryIntervalSeconds);
+
+ _timerProvider.StartTimer(timer, TimeSpan.FromSeconds(retryIntervalSeconds));
+ }
+ else
+ {
+ _timerProvider.Delete(timer);
+ _recordingProvider.Delete(recording);
}
}
@@ -752,7 +885,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
private void SaveEpgDataForChannel(string channelId, List<ProgramInfo> epgData)
{
var path = GetChannelEpgCachePath(channelId);
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
lock (_epgLock)
{
_jsonSerializer.SerializeToFile(epgData, path);
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
index 75dec5f97..2c8917ab4 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
@@ -16,13 +17,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
protected readonly ILogger Logger;
private readonly string _dataPath;
protected readonly Func<T, T, bool> EqualityComparer;
+ private readonly IFileSystem _fileSystem;
- public ItemDataProvider(IJsonSerializer jsonSerializer, ILogger logger, string dataPath, Func<T, T, bool> equalityComparer)
+ public ItemDataProvider(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, Func<T, T, bool> equalityComparer)
{
Logger = logger;
_dataPath = dataPath;
EqualityComparer = equalityComparer;
_jsonSerializer = jsonSerializer;
+ _fileSystem = fileSystem;
}
public IReadOnlyList<T> GetAll()
@@ -69,7 +72,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
private void UpdateList(List<T> newList)
{
var file = _dataPath + ".json";
- Directory.CreateDirectory(Path.GetDirectoryName(file));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(file));
lock (_fileDataLock)
{
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs
index eab278eb4..563658885 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs
@@ -2,13 +2,14 @@
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
public class SeriesTimerManager : ItemDataProvider<SeriesTimerInfo>
{
- public SeriesTimerManager(IJsonSerializer jsonSerializer, ILogger logger, string dataPath)
- : base(jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase))
+ public SeriesTimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath)
+ : base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase))
{
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
index 3ae38f382..64a5b7339 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
@@ -7,6 +7,7 @@ using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
@@ -16,8 +17,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public event EventHandler<GenericEventArgs<TimerInfo>> TimerFired;
- public TimerManager(IJsonSerializer jsonSerializer, ILogger logger, string dataPath)
- : base(jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase))
+ public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath)
+ : base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase))
{
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
index d53c08150..868889ba7 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
@@ -216,20 +216,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
// Helper.logger.Info("Modifyin channel " + channel.Number);
if (_channelPair.ContainsKey(channel.Number))
{
- string channelName;
if (_channelPair[channel.Number].logo != null)
{
channel.ImageUrl = _channelPair[channel.Number].logo.URL;
channel.HasImage = true;
}
- if (_channelPair[channel.Number].affiliate != null)
- {
- channelName = _channelPair[channel.Number].affiliate;
- }
- else
- {
- channelName = _channelPair[channel.Number].name;
- }
+ string channelName = _channelPair[channel.Number].name;
channel.Name = channelName;
}
else
@@ -245,8 +237,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
ScheduleDirect.ProgramDetails details)
{
//_logger.Debug("Show type is: " + (details.showType ?? "No ShowType"));
- DateTime startAt = DateTime.ParseExact(programInfo.airDateTime, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'",
- CultureInfo.InvariantCulture);
+ DateTime startAt = GetDate(programInfo.airDateTime);
DateTime endAt = startAt.AddSeconds(programInfo.duration);
ProgramAudio audioType = ProgramAudio.Stereo;
@@ -369,6 +360,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
return info;
}
+ private DateTime GetDate(string value)
+ {
+ var date = DateTime.ParseExact(value, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", CultureInfo.InvariantCulture);
+
+ if (date.Kind != DateTimeKind.Utc)
+ {
+ date = DateTime.SpecifyKind(date, DateTimeKind.Utc);
+ }
+ return date;
+ }
+
private string GetProgramLogo(string apiUrl, ScheduleDirect.ShowImages images)
{
string url = "";
@@ -408,7 +410,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
{
imageIdString += "\"" + i.Substring(0, 10) + "\",";
}
- ;
});
imageIdString = imageIdString.TrimEnd(',') + "]";
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index d73b144b8..0a33d7383 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -580,7 +580,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
item.Name = channelInfo.Name;
}
- await item.RefreshMetadata(new MetadataRefreshOptions
+ await item.RefreshMetadata(new MetadataRefreshOptions(_fileSystem)
{
ForceSave = isNew,
ReplaceImages = replaceImages.Distinct().ToList()
@@ -659,7 +659,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
}
- _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions());
+ _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem));
return item;
}
@@ -759,7 +759,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
}
- _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions());
+ _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem));
return item.Id;
}
@@ -1082,6 +1082,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
await CleanDatabaseInternal(newChannelIdList, new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false);
await CleanDatabaseInternal(newProgramIdList, new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false);
+ var coreService = _services.OfType<EmbyTV.EmbyTV>().FirstOrDefault();
+
+ if (coreService != null)
+ {
+ await coreService.RefreshSeriesTimers(cancellationToken, new Progress<double>()).ConfigureAwait(false);
+ }
+
// Load these now which will prefetch metadata
var dtoOptions = new DtoOptions();
dtoOptions.Fields.Remove(ItemFields.SyncInfo);
@@ -1155,7 +1162,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var program in channelPrograms)
{
+ if (program.StartDate.Kind != DateTimeKind.Utc)
+ {
+ _logger.Error("{0} returned StartDate.DateTimeKind.{1} instead of UTC for program {2}", service.Name, program.StartDate.Kind.ToString(), program.Name);
+ }
+ else if (program.EndDate.Kind != DateTimeKind.Utc)
+ {
+ _logger.Error("{0} returned EndDate.DateTimeKind.{1} instead of UTC for program {2}", service.Name, program.EndDate.Kind.ToString(), program.Name);
+ }
+
var programItem = await GetProgram(program, channelId, currentChannel.ChannelType, service.Name, cancellationToken).ConfigureAwait(false);
+
programs.Add(programItem.Id);
}
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs
index 909e2bba5..e5222e55d 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs
@@ -109,23 +109,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
foreach (var host in hostsWithChannel)
{
- // Check to make sure the tuner is available
- // If there's only one tuner, don't bother with the check and just let the tuner be the one to throw an error
- if (hostsWithChannel.Count > 1 && !await IsAvailable(host, channelId, cancellationToken).ConfigureAwait(false))
+ try
{
- Logger.Error("Tuner is not currently available");
- continue;
- }
+ var mediaSources = await GetChannelStreamMediaSources(host, channelId, cancellationToken).ConfigureAwait(false);
- var mediaSources = await GetChannelStreamMediaSources(host, channelId, cancellationToken).ConfigureAwait(false);
+ // Prefix the id with the host Id so that we can easily find it
+ foreach (var mediaSource in mediaSources)
+ {
+ mediaSource.Id = host.Id + mediaSource.Id;
+ }
- // Prefix the id with the host Id so that we can easily find it
- foreach (var mediaSource in mediaSources)
+ return mediaSources;
+ }
+ catch (Exception ex)
{
- mediaSource.Id = host.Id + mediaSource.Id;
+ Logger.Error("Error opening tuner", ex);
}
-
- return mediaSources;
}
}
@@ -163,23 +162,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
foreach (var host in hostsWithChannel)
{
- // Check to make sure the tuner is available
- // If there's only one tuner, don't bother with the check and just let the tuner be the one to throw an error
- // If a streamId is specified then availibility has already been checked in GetChannelStreamMediaSources
- if (string.IsNullOrWhiteSpace(streamId) && hostsWithChannel.Count > 1)
+ try
{
- if (!await IsAvailable(host, channelId, cancellationToken).ConfigureAwait(false))
+ var stream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false);
+
+ if (stream != null)
{
- Logger.Error("Tuner is not currently available");
- continue;
+ return stream;
}
}
-
- var stream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false);
-
- if (stream != null)
+ catch (Exception ex)
{
- return stream;
+ Logger.Error("Error opening tuner", ex);
}
}
}
@@ -187,21 +181,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
throw new LiveTvConflictException();
}
- protected async Task<bool> IsAvailable(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
- {
- try
- {
- return await IsAvailableInternal(tuner, channelId, cancellationToken).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error checking tuner availability", ex);
- return false;
- }
- }
-
- protected abstract Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken);
-
protected abstract bool IsValidChannelId(string channelId);
protected LiveTvOptions GetConfiguration()
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index bccb0db0a..571b00257 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -325,11 +325,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
BitRate = 128000
}
},
- RequiresOpening = false,
- RequiresClosing = false,
+ RequiresOpening = true,
+ RequiresClosing = true,
BufferMs = 1000,
Container = "ts",
- Id = profile
+ Id = profile,
+ SupportsDirectPlay = true,
+ SupportsDirectStream = true,
+ SupportsTranscoding = true
};
return mediaSource;
@@ -395,12 +398,5 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
await GetChannels(info, false, CancellationToken.None).ConfigureAwait(false);
}
}
-
- protected override async Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
- {
- var info = await GetTunerInfos(tuner, cancellationToken).ConfigureAwait(false);
-
- return info.Any(i => i.Status == LiveTvTunerStatus.Available || string.Equals(i.ChannelId, channelId, StringComparison.OrdinalIgnoreCase));
- }
}
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
index 3783e4b08..31139b15d 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
@@ -12,14 +12,18 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
{
public class M3UTunerHost : BaseTunerHost, ITunerHost
{
- public M3UTunerHost(IConfigurationManager config, ILogger logger)
+ private readonly IFileSystem _fileSystem;
+
+ public M3UTunerHost(IConfigurationManager config, ILogger logger, IFileSystem fileSystem)
: base(config, logger)
{
+ _fileSystem = fileSystem;
}
public override string Type
@@ -119,7 +123,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
public async Task Validate(TunerHostInfo info)
{
- if (!File.Exists(info.Url))
+ if (!_fileSystem.FileExists(info.Url))
{
throw new FileNotFoundException();
}
@@ -190,10 +194,5 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
}
return new List<MediaSourceInfo> { };
}
-
- protected override Task<bool> IsAvailableInternal(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
- {
- return Task.FromResult(true);
- }
}
}
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ar.json b/MediaBrowser.Server.Implementations/Localization/Core/ar.json
index 3d15d7b2e..fd47027c2 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/ar.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/ar.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/bg-BG.json b/MediaBrowser.Server.Implementations/Localization/Core/bg-BG.json
index 8854611a0..d719ae08e 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/bg-BG.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/bg-BG.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ca.json b/MediaBrowser.Server.Implementations/Localization/Core/ca.json
index 35f2bafb8..46004f52c 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/ca.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/ca.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/core.json b/MediaBrowser.Server.Implementations/Localization/Core/core.json
index 4eb66929d..5f11b9436 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/core.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/core.json
@@ -173,5 +173,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
}
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/cs.json b/MediaBrowser.Server.Implementations/Localization/Core/cs.json
index ee30a6028..771e735e9 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/cs.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/cs.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/da.json b/MediaBrowser.Server.Implementations/Localization/Core/da.json
index 21d7e9e14..e6e4d9835 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/da.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/da.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Aldersgr\u00e6nser",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/de.json b/MediaBrowser.Server.Implementations/Localization/Core/de.json
index 277a224ce..0464b65ac 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/de.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/de.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Produzenten",
"HeaderWriter": "Autoren",
"HeaderParentalRatings": "Altersbeschr\u00e4nkung",
- "HeaderCommunityRatings": "Community Bewertungen"
+ "HeaderCommunityRatings": "Community Bewertungen",
+ "StartupEmbyServerIsLoading": "Emby Server startet, bitte versuchen Sie es gleich noch einmal."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/el.json b/MediaBrowser.Server.Implementations/Localization/Core/el.json
index 213868042..7e94f7987 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/el.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/el.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/en-GB.json b/MediaBrowser.Server.Implementations/Localization/Core/en-GB.json
index 566d2cf09..73534b08d 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/en-GB.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/en-GB.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/en-US.json b/MediaBrowser.Server.Implementations/Localization/Core/en-US.json
index abe203804..e444c0e93 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/en-US.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/en-US.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/es-AR.json b/MediaBrowser.Server.Implementations/Localization/Core/es-AR.json
index 9c1ea6cb9..8068e32a9 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/es-AR.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/es-AR.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/es-MX.json b/MediaBrowser.Server.Implementations/Localization/Core/es-MX.json
index 9e1030dbd..972f94100 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/es-MX.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/es-MX.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Productores",
"HeaderWriter": "Guionistas",
"HeaderParentalRatings": "Clasificaci\u00f3n Parental",
- "HeaderCommunityRatings": "Clasificaciones de la comunidad"
+ "HeaderCommunityRatings": "Clasificaciones de la comunidad",
+ "StartupEmbyServerIsLoading": "El servidor Emby esta cargando. Por favor intente de nuevo dentro de poco."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/es.json b/MediaBrowser.Server.Implementations/Localization/Core/es.json
index f93fd7219..9bf56e4af 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/es.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/es.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/fi.json b/MediaBrowser.Server.Implementations/Localization/Core/fi.json
index 5df95146c..f0ab5b0d0 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/fi.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/fi.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/fr.json b/MediaBrowser.Server.Implementations/Localization/Core/fr.json
index fe76ac64e..d8bffe699 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/fr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/fr.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producteurs",
"HeaderWriter": "Auteur(e)s",
"HeaderParentalRatings": "Note parentale",
- "HeaderCommunityRatings": "Classification de la communaut\u00e9"
+ "HeaderCommunityRatings": "Classification de la communaut\u00e9",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/gsw.json b/MediaBrowser.Server.Implementations/Localization/Core/gsw.json
index 7334b24ce..736c3d18f 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/gsw.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/gsw.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/he.json b/MediaBrowser.Server.Implementations/Localization/Core/he.json
index b3bec3f02..a66438482 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/he.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/he.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/hr.json b/MediaBrowser.Server.Implementations/Localization/Core/hr.json
index 451ff4f36..2b9d56566 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/hr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/hr.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/it.json b/MediaBrowser.Server.Implementations/Localization/Core/it.json
index 90f800634..197b9e2bb 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/it.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/it.json
@@ -20,8 +20,8 @@
"LabelExit": "Esci",
"LabelVisitCommunity": "Visita la Community",
"LabelGithub": "Github",
- "LabelApiDocumentation": "Documentazione sulle Api",
- "LabelDeveloperResources": "Risorse per i programmatori",
+ "LabelApiDocumentation": "Documentazione Api",
+ "LabelDeveloperResources": "Risorse programmatori",
"LabelBrowseLibrary": "Esplora la libreria",
"LabelConfigureServer": "Configura Emby",
"LabelRestartServer": "Riavvia Server",
@@ -120,36 +120,36 @@
"UserStartedPlayingItemWithValues": "{0} \u00e8 partito da {1}",
"UserStoppedPlayingItemWithValues": "{0} stoppato {1}",
"SubtitleDownloadFailureForItem": "Sottotitoli non scaricati per {0}",
- "HeaderUnidentified": "Unidentified",
- "HeaderImagePrimary": "Primary",
- "HeaderImageBackdrop": "Backdrop",
+ "HeaderUnidentified": "Non identificata",
+ "HeaderImagePrimary": "Primaria",
+ "HeaderImageBackdrop": "Sfondo",
"HeaderImageLogo": "Logo",
- "HeaderUserPrimaryImage": "User Image",
- "HeaderOverview": "Overview",
- "HeaderShortOverview": "Short Overview",
- "HeaderType": "Type",
- "HeaderSeverity": "Severity",
+ "HeaderUserPrimaryImage": "Immagine utente",
+ "HeaderOverview": "Panoramica",
+ "HeaderShortOverview": "breve panoramica",
+ "HeaderType": "Tipo",
+ "HeaderSeverity": "gravit\u00e0",
"HeaderUser": "Utente",
"HeaderName": "Nome",
"HeaderDate": "Data",
"HeaderPremiereDate": "Premiere Date",
- "HeaderDateAdded": "Date Added",
+ "HeaderDateAdded": "Aggiunto il",
"HeaderReleaseDate": "Data Rilascio",
"HeaderRuntime": "Durata",
- "HeaderPlayCount": "Play Count",
+ "HeaderPlayCount": "Visto N\u00b0",
"HeaderSeason": "Stagione",
"HeaderSeasonNumber": "Stagione Numero",
- "HeaderSeries": "Series:",
+ "HeaderSeries": "Serie:",
"HeaderNetwork": "Rete",
- "HeaderYear": "Year:",
- "HeaderYears": "Years:",
- "HeaderParentalRating": "Parental Rating",
+ "HeaderYear": "Anno:",
+ "HeaderYears": "Anni",
+ "HeaderParentalRating": "Valutazione parentale",
"HeaderCommunityRating": "Voto Comunit\u00e0",
"HeaderTrailers": "Trailers",
"HeaderSpecials": "Speciali",
- "HeaderGameSystems": "Game Systems",
- "HeaderPlayers": "Players:",
- "HeaderAlbumArtists": "Album Artists",
+ "HeaderGameSystems": "Sistemi di gioco",
+ "HeaderPlayers": "Giocatori",
+ "HeaderAlbumArtists": "Album Artisti",
"HeaderAlbums": "Album",
"HeaderDisc": "Disco",
"HeaderTrack": "Traccia",
@@ -163,14 +163,15 @@
"HeaderStatus": "Stato",
"HeaderTracks": "Traccia",
"HeaderMusicArtist": "Music artist",
- "HeaderLocked": "Locked",
+ "HeaderLocked": "Bloccato",
"HeaderStudios": "Studios",
- "HeaderActor": "Actors",
- "HeaderComposer": "Composers",
- "HeaderDirector": "Directors",
- "HeaderGuestStar": "Guest star",
- "HeaderProducer": "Producers",
- "HeaderWriter": "Writers",
+ "HeaderActor": "Attori",
+ "HeaderComposer": "Compositori",
+ "HeaderDirector": "Registi",
+ "HeaderGuestStar": "Personaggi famosi",
+ "HeaderProducer": "Produttori",
+ "HeaderWriter": "Sceneggiatori",
"HeaderParentalRatings": "Valutazioni genitori",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/kk.json b/MediaBrowser.Server.Implementations/Localization/Core/kk.json
index 7e17dea6b..863523606 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/kk.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/kk.json
@@ -104,7 +104,7 @@
"DeviceOnlineWithName": "{0} \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d",
"UserOnlineFromDevice": "{0} - {1} \u0430\u0440\u049b\u044b\u043b\u044b \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d",
"ProviderValue": "\u0416\u0435\u0442\u043a\u0456\u0437\u0443\u0448\u0456: {0}",
- "SubtitlesDownloadedForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 {0} \u04af\u0448\u0456\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0434\u044b",
+ "SubtitlesDownloadedForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 {0} \u04af\u0448\u0456\u043d \u0436\u04af\u043a\u0442\u0435\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0434\u044b",
"UserConfigurationUpdatedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b",
"UserCreatedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u0436\u0430\u0441\u0430\u043b\u0493\u0430\u043d",
"UserPasswordChangedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u04af\u0448\u0456\u043d \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437 \u04e9\u0437\u0433\u0435\u0440\u0442\u0456\u043b\u0434\u0456",
@@ -117,9 +117,9 @@
"DeviceOfflineWithName": "{0} \u0430\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0493\u0430\u043d",
"UserLockedOutWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u049b\u04b1\u0440\u0441\u0430\u0443\u043b\u044b",
"UserOfflineFromDevice": "{0} - {1} \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0493\u0430\u043d",
- "UserStartedPlayingItemWithValues": "{0} - {1} \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u0431\u0430\u0441\u0442\u0430\u043b\u0434\u044b",
- "UserStoppedPlayingItemWithValues": "{0} - {1} \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u0442\u043e\u049b\u0442\u0430\u043b\u0434\u044b",
- "SubtitleDownloadFailureForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 {0} \u04af\u0448\u0456\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0443\u044b \u0441\u04d9\u0442\u0441\u0456\u0437",
+ "UserStartedPlayingItemWithValues": "{0} - {1} \u043e\u0439\u043d\u0430\u0442\u0443\u044b\u043d \u0431\u0430\u0441\u0442\u0430\u0434\u044b",
+ "UserStoppedPlayingItemWithValues": "{0} - {1} \u043e\u0439\u043d\u0430\u0442\u0443\u044b\u043d \u0442\u043e\u049b\u0442\u0430\u0442\u0442\u044b",
+ "SubtitleDownloadFailureForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 {0} \u04af\u0448\u0456\u043d \u0436\u04af\u043a\u0442\u0435\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0443\u044b \u0441\u04d9\u0442\u0441\u0456\u0437",
"HeaderUnidentified": "\u0410\u043d\u044b\u049b\u0442\u0430\u043b\u043c\u0430\u0493\u0430\u043d",
"HeaderImagePrimary": "\u041d\u0435\u0433\u0456\u0437\u0433\u0456",
"HeaderImageBackdrop": "\u0410\u0440\u0442\u049b\u044b \u0441\u0443\u0440\u0435\u0442",
@@ -172,5 +172,6 @@
"HeaderProducer": "\u041f\u0440\u043e\u0434\u044e\u0441\u0435\u0440\u043b\u0435\u0440",
"HeaderWriter": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439\u0448\u0456\u043b\u0435\u0440",
"HeaderParentalRatings": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u0442\u0430\u0440",
- "HeaderCommunityRatings": "\u049a\u0430\u0443\u044b\u043c \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u043b\u0430\u0440\u044b"
+ "HeaderCommunityRatings": "\u049a\u0430\u0443\u044b\u043c \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u043b\u0430\u0440\u044b",
+ "StartupEmbyServerIsLoading": "Emby Server \u0436\u04af\u043a\u0442\u0435\u043b\u0443\u0434\u0435. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u043a\u04e9\u043f \u04b1\u0437\u0430\u043c\u0430\u0439 \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ko.json b/MediaBrowser.Server.Implementations/Localization/Core/ko.json
index 8bc5b5672..6044efb62 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/ko.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/ko.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ms.json b/MediaBrowser.Server.Implementations/Localization/Core/ms.json
index a85f00132..6b5c4393f 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/ms.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/ms.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/nb.json b/MediaBrowser.Server.Implementations/Localization/Core/nb.json
index 2ab601701..f4ebe89b6 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/nb.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/nb.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Foreldresensur",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/nl.json b/MediaBrowser.Server.Implementations/Localization/Core/nl.json
index 8658518a4..b32ebefc3 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/nl.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/nl.json
@@ -157,7 +157,7 @@
"HeaderVideo": "Video",
"HeaderEmbeddedImage": "Ingesloten afbeelding",
"HeaderResolution": "Resolutie",
- "HeaderSubtitles": "Ondertitels",
+ "HeaderSubtitles": "Ondertiteling",
"HeaderGenres": "Genres",
"HeaderCountries": "Landen",
"HeaderStatus": "Status",
@@ -172,5 +172,6 @@
"HeaderProducer": "Producenten",
"HeaderWriter": "Schrijvers",
"HeaderParentalRatings": "Ouderlijke toezicht",
- "HeaderCommunityRatings": "Gemeenschapswaardering"
+ "HeaderCommunityRatings": "Gemeenschapswaardering",
+ "StartupEmbyServerIsLoading": "Emby Server is aan het laden, probeer het later opnieuw."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/pl.json b/MediaBrowser.Server.Implementations/Localization/Core/pl.json
index b7b0e228e..13dca8889 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/pl.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/pl.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/pt-BR.json b/MediaBrowser.Server.Implementations/Localization/Core/pt-BR.json
index e5e8afaa5..9548262c9 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/pt-BR.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/pt-BR.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Produtores",
"HeaderWriter": "Escritores",
"HeaderParentalRatings": "Classifica\u00e7\u00f5es Parentais",
- "HeaderCommunityRatings": "Avalia\u00e7\u00f5es da comunidade"
+ "HeaderCommunityRatings": "Avalia\u00e7\u00f5es da comunidade",
+ "StartupEmbyServerIsLoading": "O Servidor Emby est\u00e1 carregando. Por favor, tente novamente em breve."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/pt-PT.json b/MediaBrowser.Server.Implementations/Localization/Core/pt-PT.json
index 5aa832e16..c3d514c8a 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/pt-PT.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/pt-PT.json
@@ -46,7 +46,7 @@
"NotificationOptionInstallationFailed": "Falha na instala\u00e7\u00e3o",
"NotificationOptionNewLibraryContent": "Adicionado novo conte\u00fado",
"NotificationOptionNewLibraryContentMultiple": "Novo conte\u00fado adicionado (m\u00faltiplo)",
- "NotificationOptionCameraImageUploaded": "Camera image uploaded",
+ "NotificationOptionCameraImageUploaded": "Imagem da c\u00e2mara carregada",
"NotificationOptionUserLockedOut": "User locked out",
"NotificationOptionServerRestartRequired": "\u00c9 necess\u00e1rio reiniciar o servidor",
"ViewTypePlaylists": "Playlists",
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ro.json b/MediaBrowser.Server.Implementations/Localization/Core/ro.json
index 6c945006a..a6aa9577b 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/ro.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/ro.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ru.json b/MediaBrowser.Server.Implementations/Localization/Core/ru.json
index c705ddef4..f36db9e25 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/ru.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/ru.json
@@ -46,7 +46,7 @@
"NotificationOptionInstallationFailed": "\u0421\u0431\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438",
"NotificationOptionNewLibraryContent": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e",
"NotificationOptionNewLibraryContentMultiple": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e (\u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e)",
- "NotificationOptionCameraImageUploaded": "\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044f \u0441 \u043a\u0430\u043c\u0435\u0440\u044b \u0432\u044b\u043b\u043e\u0436\u0435\u043d\u0430",
+ "NotificationOptionCameraImageUploaded": "\u041f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0430 \u0432\u044b\u043a\u043b\u0430\u0434\u043a\u0430 \u043e\u0442\u0441\u043d\u044f\u0442\u043e\u0433\u043e \u0441 \u043a\u0430\u043c\u0435\u0440\u044b",
"NotificationOptionUserLockedOut": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d",
"NotificationOptionServerRestartRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430",
"ViewTypePlaylists": "\u0421\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
@@ -81,7 +81,7 @@
"ViewTypeMusicLatest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435",
"ViewTypeMusicPlaylists": "\u0421\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
"ViewTypeMusicAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u044b",
- "ViewTypeMusicAlbumArtists": "\u0410\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438",
+ "ViewTypeMusicAlbumArtists": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438 \u0430\u043b\u044c\u0431\u043e\u043c\u0430",
"HeaderOtherDisplaySettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f",
"ViewTypeMusicSongs": "\u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u0438",
"ViewTypeMusicFavorites": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435",
@@ -117,11 +117,11 @@
"DeviceOfflineWithName": "{0} - \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0440\u0432\u0430\u043d\u043e",
"UserLockedOutWithName": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c {0} \u0431\u044b\u043b \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d",
"UserOfflineFromDevice": "{0} - \u043f\u043e\u0434\u043a\u043b. \u0441 {1} \u043f\u0440\u0435\u0440\u0432\u0430\u043d\u043e",
- "UserStartedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440-\u0438\u0435 \u00ab{1}\u00bb \u0437\u0430\u043f-\u043d\u043e",
- "UserStoppedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440-\u0438\u0435 \u00ab{1}\u00bb \u043e\u0441\u0442-\u043d\u043e",
+ "UserStartedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440. \u00ab{1}\u00bb \u0437\u0430\u043f-\u043d\u043e",
+ "UserStoppedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440. \u00ab{1}\u00bb \u043e\u0441\u0442-\u043d\u043e",
"SubtitleDownloadFailureForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u043a {0} \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c",
"HeaderUnidentified": "\u041d\u0435 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u043e",
- "HeaderImagePrimary": "\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439",
+ "HeaderImagePrimary": "\u0413\u043e\u043b\u043e\u0432\u043d\u043e\u0439",
"HeaderImageBackdrop": "\u0417\u0430\u0434\u043d\u0438\u043a",
"HeaderImageLogo": "\u041b\u043e\u0433\u043e\u0442\u0438\u043f",
"HeaderUserPrimaryImage": "\u0420\u0438\u0441\u0443\u043d\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
@@ -133,23 +133,23 @@
"HeaderName": "\u0418\u043c\u044f (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435)",
"HeaderDate": "\u0414\u0430\u0442\u0430",
"HeaderPremiereDate": "\u0414\u0430\u0442\u0430 \u043f\u0440\u0435\u043c\u044c\u0435\u0440\u044b",
- "HeaderDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431-\u0438\u044f",
+ "HeaderDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431.",
"HeaderReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u043f.",
"HeaderRuntime": "\u0414\u043b\u0438\u0442.",
- "HeaderPlayCount": "\u0427\u0438\u0441\u043b\u043e \u0432\u043e\u0441\u043f\u0440-\u0438\u0439",
+ "HeaderPlayCount": "\u041a\u043e\u043b-\u0432\u043e \u0432\u043e\u0441\u043f\u0440.",
"HeaderSeason": "\u0421\u0435\u0437\u043e\u043d",
- "HeaderSeasonNumber": "\u041d\u043e\u043c\u0435\u0440 \u0441\u0435\u0437\u043e\u043d\u0430",
+ "HeaderSeasonNumber": "\u2116 \u0441\u0435\u0437\u043e\u043d\u0430",
"HeaderSeries": "\u0421\u0435\u0440\u0438\u0430\u043b:",
"HeaderNetwork": "\u0422\u0435\u043b\u0435\u0441\u0435\u0442\u044c",
"HeaderYear": "\u0413\u043e\u0434:",
"HeaderYears": "\u0413\u043e\u0434\u044b:",
- "HeaderParentalRating": "\u0412\u043e\u0437\u0440. \u043a\u0430\u0442-\u0438\u044f",
+ "HeaderParentalRating": "\u0412\u043e\u0437\u0440. \u043a\u0430\u0442.",
"HeaderCommunityRating": "\u041e\u0431\u0449. \u043e\u0446\u0435\u043d\u043a\u0430",
"HeaderTrailers": "\u0422\u0440\u0435\u0439\u043b.",
"HeaderSpecials": "\u0421\u043f\u0435\u0446.",
"HeaderGameSystems": "\u0418\u0433\u0440. \u0441\u0438\u0441\u0442\u0435\u043c\u044b",
"HeaderPlayers": "\u0418\u0433\u0440\u043e\u043a\u0438:",
- "HeaderAlbumArtists": "\u0410\u043b\u044c\u0431\u043e\u043c. \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438",
+ "HeaderAlbumArtists": "\u0418\u0441\u043f-\u043b\u0438 \u0430\u043b\u044c\u0431\u043e\u043c\u0430",
"HeaderAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u044b",
"HeaderDisc": "\u0414\u0438\u0441\u043a",
"HeaderTrack": "\u0414\u043e\u0440-\u043a\u0430",
@@ -172,5 +172,6 @@
"HeaderProducer": "\u041f\u0440\u043e\u0434\u044e\u0441\u0435\u0440\u044b",
"HeaderWriter": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0441\u0442\u044b",
"HeaderParentalRatings": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f",
- "HeaderCommunityRatings": "\u041e\u0431\u0449. \u043e\u0446\u0435\u043d\u043a\u0438"
+ "HeaderCommunityRatings": "\u041e\u0431\u0449. \u043e\u0446\u0435\u043d\u043a\u0438",
+ "StartupEmbyServerIsLoading": "Emby Server \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u0432\u0441\u043a\u043e\u0440\u0435."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/sl-SI.json b/MediaBrowser.Server.Implementations/Localization/Core/sl-SI.json
index abe203804..e444c0e93 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/sl-SI.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/sl-SI.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/sv.json b/MediaBrowser.Server.Implementations/Localization/Core/sv.json
index 3a5a322c6..667b8e4b4 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/sv.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/sv.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/tr.json b/MediaBrowser.Server.Implementations/Localization/Core/tr.json
index f127cc816..810df2665 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/tr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/tr.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/uk.json b/MediaBrowser.Server.Implementations/Localization/Core/uk.json
index ec9ca5a39..73c9b26f9 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/uk.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/uk.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/vi.json b/MediaBrowser.Server.Implementations/Localization/Core/vi.json
index 6e0c3ea20..75a5dbea7 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/vi.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/vi.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/zh-CN.json b/MediaBrowser.Server.Implementations/Localization/Core/zh-CN.json
index 54cd7e59b..3368e5ccd 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/zh-CN.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/zh-CN.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "\u5bb6\u957f\u5206\u7ea7",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/zh-HK.json b/MediaBrowser.Server.Implementations/Localization/Core/zh-HK.json
new file mode 100644
index 000000000..8b5a8ff0d
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/Core/zh-HK.json
@@ -0,0 +1,177 @@
+{
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "UserDownloadingItemWithValues": "{0} is downloading {1}",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "\u7e7c\u627f",
+ "HeaderCastCrew": "\u6f14\u54e1\u9663\u5bb9",
+ "HeaderPeople": "People",
+ "ValueSpecialEpisodeName": "Special - {0}",
+ "LabelChapterName": "Chapter {0}",
+ "NameSeasonNumber": "Season {0}",
+ "LabelExit": "\u96e2\u958b",
+ "LabelVisitCommunity": "\u8a2a\u554f\u8a0e\u8ad6\u5340",
+ "LabelGithub": "Github",
+ "LabelApiDocumentation": "Api \u6587\u4ef6",
+ "LabelDeveloperResources": "\u958b\u767c\u8005\u8cc7\u6e90",
+ "LabelBrowseLibrary": "\u700f\u89bd\u8cc7\u6599\u5eab",
+ "LabelConfigureServer": "\u8a2d\u7f6e Emby",
+ "LabelRestartServer": "\u91cd\u555f\u4f3a\u670d\u5668",
+ "CategorySync": "\u540c\u6b65",
+ "CategoryUser": "User",
+ "CategorySystem": "System",
+ "CategoryApplication": "Application",
+ "CategoryPlugin": "Plugin",
+ "NotificationOptionPluginError": "Plugin failure",
+ "NotificationOptionApplicationUpdateAvailable": "Application update available",
+ "NotificationOptionApplicationUpdateInstalled": "Application update installed",
+ "NotificationOptionPluginUpdateInstalled": "Plugin update installed",
+ "NotificationOptionPluginInstalled": "Plugin installed",
+ "NotificationOptionPluginUninstalled": "Plugin uninstalled",
+ "NotificationOptionVideoPlayback": "Video playback started",
+ "NotificationOptionAudioPlayback": "Audio playback started",
+ "NotificationOptionGamePlayback": "Game playback started",
+ "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
+ "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
+ "NotificationOptionGamePlaybackStopped": "Game playback stopped",
+ "NotificationOptionTaskFailed": "Scheduled task failure",
+ "NotificationOptionInstallationFailed": "Installation failure",
+ "NotificationOptionNewLibraryContent": "New content added",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
+ "NotificationOptionCameraImageUploaded": "Camera image uploaded",
+ "NotificationOptionUserLockedOut": "User locked out",
+ "NotificationOptionServerRestartRequired": "Server restart required",
+ "ViewTypePlaylists": "Playlists",
+ "ViewTypeMovies": "Movies",
+ "ViewTypeTvShows": "TV",
+ "ViewTypeGames": "Games",
+ "ViewTypeMusic": "Music",
+ "ViewTypeMusicGenres": "Genres",
+ "ViewTypeMusicArtists": "Artists",
+ "ViewTypeBoxSets": "Collections",
+ "ViewTypeChannels": "Channels",
+ "ViewTypeLiveTV": "Live TV",
+ "ViewTypeLiveTvNowPlaying": "Now Airing",
+ "ViewTypeLatestGames": "Latest Games",
+ "ViewTypeRecentlyPlayedGames": "Recently Played",
+ "ViewTypeGameFavorites": "Favorites",
+ "ViewTypeGameSystems": "Game Systems",
+ "ViewTypeGameGenres": "Genres",
+ "ViewTypeTvResume": "Resume",
+ "ViewTypeTvNextUp": "Next Up",
+ "ViewTypeTvLatest": "Latest",
+ "ViewTypeTvShowSeries": "Series",
+ "ViewTypeTvGenres": "Genres",
+ "ViewTypeTvFavoriteSeries": "Favorite Series",
+ "ViewTypeTvFavoriteEpisodes": "Favorite Episodes",
+ "ViewTypeMovieResume": "Resume",
+ "ViewTypeMovieLatest": "Latest",
+ "ViewTypeMovieMovies": "Movies",
+ "ViewTypeMovieCollections": "Collections",
+ "ViewTypeMovieFavorites": "Favorites",
+ "ViewTypeMovieGenres": "Genres",
+ "ViewTypeMusicLatest": "Latest",
+ "ViewTypeMusicPlaylists": "Playlists",
+ "ViewTypeMusicAlbums": "Albums",
+ "ViewTypeMusicAlbumArtists": "Album Artists",
+ "HeaderOtherDisplaySettings": "Display Settings",
+ "ViewTypeMusicSongs": "Songs",
+ "ViewTypeMusicFavorites": "Favorites",
+ "ViewTypeMusicFavoriteAlbums": "Favorite Albums",
+ "ViewTypeMusicFavoriteArtists": "Favorite Artists",
+ "ViewTypeMusicFavoriteSongs": "Favorite Songs",
+ "ViewTypeFolders": "Folders",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
+ "ViewTypeLiveTvChannels": "Channels",
+ "ScheduledTaskFailedWithName": "{0} failed",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "VersionNumber": "\u7248\u672c {0}",
+ "PluginInstalledWithName": "{0} was installed",
+ "PluginUpdatedWithName": "{0} was updated",
+ "PluginUninstalledWithName": "{0} was uninstalled",
+ "ItemAddedWithName": "{0} was added to the library",
+ "ItemRemovedWithName": "{0} was removed from the library",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "ProviderValue": "Provider: {0}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Emby Server has been updated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserLockedOutWithName": "User {0} has been locked out",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "HeaderUnidentified": "Unidentified",
+ "HeaderImagePrimary": "Primary",
+ "HeaderImageBackdrop": "Backdrop",
+ "HeaderImageLogo": "Logo",
+ "HeaderUserPrimaryImage": "User Image",
+ "HeaderOverview": "Overview",
+ "HeaderShortOverview": "Short Overview",
+ "HeaderType": "Type",
+ "HeaderSeverity": "Severity",
+ "HeaderUser": "User",
+ "HeaderName": "Name",
+ "HeaderDate": "\u65e5\u671f",
+ "HeaderPremiereDate": "Premiere Date",
+ "HeaderDateAdded": "Date Added",
+ "HeaderReleaseDate": "Release date",
+ "HeaderRuntime": "Runtime",
+ "HeaderPlayCount": "Play Count",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderSeries": "Series:",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year:",
+ "HeaderYears": "Years:",
+ "HeaderParentalRating": "Parental Rating",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderTrailers": "Trailers",
+ "HeaderSpecials": "Specials",
+ "HeaderGameSystems": "Game Systems",
+ "HeaderPlayers": "Players:",
+ "HeaderAlbumArtists": "Album Artists",
+ "HeaderAlbums": "Albums",
+ "HeaderDisc": "Disc",
+ "HeaderTrack": "Track",
+ "HeaderAudio": "Audio",
+ "HeaderVideo": "Video",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderResolution": "Resolution",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderGenres": "Genres",
+ "HeaderCountries": "Countries",
+ "HeaderStatus": "\u72c0\u614b",
+ "HeaderTracks": "Tracks",
+ "HeaderMusicArtist": "Music artist",
+ "HeaderLocked": "Locked",
+ "HeaderStudios": "Studios",
+ "HeaderActor": "Actors",
+ "HeaderComposer": "Composers",
+ "HeaderDirector": "Directors",
+ "HeaderGuestStar": "Guest star",
+ "HeaderProducer": "Producers",
+ "HeaderWriter": "Writers",
+ "HeaderParentalRatings": "Parental Ratings",
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
+} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json b/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json
index 787508176..2bcb5c132 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json
@@ -172,5 +172,6 @@
"HeaderProducer": "Producers",
"HeaderWriter": "Writers",
"HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings"
+ "HeaderCommunityRatings": "Community ratings",
+ "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
index 8c893c8d1..e776f4311 100644
--- a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
+++ b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
@@ -58,7 +58,7 @@ namespace MediaBrowser.Server.Implementations.Localization
var localizationPath = LocalizationPath;
- Directory.CreateDirectory(localizationPath);
+ _fileSystem.CreateDirectory(localizationPath);
var existingFiles = Directory.EnumerateFiles(localizationPath, "ratings-*.txt", SearchOption.TopDirectoryOnly)
.Select(Path.GetFileName)
@@ -212,7 +212,7 @@ namespace MediaBrowser.Server.Implementations.Localization
/// <returns>Dictionary{System.StringParentalRating}.</returns>
private void LoadRatings(string file)
{
- var dict = File.ReadAllLines(file).Select(i =>
+ var dict = File.ReadAllLines(file).Select(i =>
{
if (!string.IsNullOrWhiteSpace(i))
{
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index f0312cef6..7d2d74140 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -11,10 +11,10 @@
<AssemblyName>MediaBrowser.Server.Implementations</AssemblyName>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
- <ProductVersion>10.0.0</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<RestorePackages>true</RestorePackages>
+ <ReleaseVersion>
+ </ReleaseVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -24,7 +24,6 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@@ -33,7 +32,6 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Mono|AnyCPU' ">
<DebugType>none</DebugType>
@@ -42,35 +40,17 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
- <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Interfaces.IO">
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
</Reference>
- <Reference Include="MediaBrowser.Naming, Version=1.0.5614.25103, Culture=neutral, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\MediaBrowser.Naming.1.0.0.37\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
- </Reference>
- <Reference Include="Mono.Nat, Version=1.2.24.0, Culture=neutral, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll</HintPath>
- </Reference>
- <Reference Include="MoreLinq, Version=1.1.17511.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\morelinq.1.1.0\lib\net35\MoreLinq.dll</HintPath>
- </Reference>
<Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
- <Private>True</Private>
</Reference>
<Reference Include="ServiceStack.Api.Swagger">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
</Reference>
- <Reference Include="SocketHttpListener, Version=1.0.5634.16042, Culture=neutral, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\SocketHttpListener.1.0.0.7\lib\net45\SocketHttpListener.dll</HintPath>
- </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite">
@@ -100,6 +80,18 @@
<Reference Include="UniversalDetector">
<HintPath>..\ThirdParty\UniversalDetector\UniversalDetector.dll</HintPath>
</Reference>
+ <Reference Include="MediaBrowser.Naming">
+ <HintPath>..\packages\MediaBrowser.Naming.1.0.0.37\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
+ </Reference>
+ <Reference Include="Mono.Nat">
+ <HintPath>..\packages\Mono.Nat.1.2.24.0\lib\net40\Mono.Nat.dll</HintPath>
+ </Reference>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.1.1\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
+ <Reference Include="SocketHttpListener">
+ <HintPath>..\packages\SocketHttpListener.1.0.0.7\lib\net45\SocketHttpListener.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
@@ -334,7 +326,6 @@
<Compile Include="Sync\SyncRepository.cs" />
<Compile Include="Sync\SyncConvertScheduledTask.cs" />
<Compile Include="Sync\TargetDataProvider.cs" />
- <Compile Include="Themes\AppThemeManager.cs" />
<Compile Include="TV\TVSeriesManager.cs" />
<Compile Include="Udp\UdpMessageReceivedEventArgs.cs" />
<Compile Include="Udp\UdpServer.cs" />
@@ -413,6 +404,7 @@
<EmbeddedResource Include="Localization\Core\vi.json" />
<EmbeddedResource Include="Localization\Core\zh-CN.json" />
<EmbeddedResource Include="Localization\Core\zh-TW.json" />
+ <EmbeddedResource Include="Localization\Core\zh-HK.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
index 6b99883a5..9ea553d2d 100644
--- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -138,7 +138,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
try
{
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
using (var stream = await _encoder.ExtractVideoImage(inputPath, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false))
{
diff --git a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs b/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs
index 619384b6f..0266756c3 100644
--- a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs
@@ -71,7 +71,7 @@ namespace MediaBrowser.Server.Implementations.News
{
DateTime? lastUpdate = null;
- if (File.Exists(path))
+ if (_fileSystem.FileExists(path))
{
lastUpdate = _fileSystem.GetLastWriteTimeUtc(path);
}
diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
index 9f87483ba..c9f7165cb 100644
--- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs
@@ -1,15 +1,18 @@
-using MediaBrowser.Common.Progress;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Progress;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Entities.Audio;
namespace MediaBrowser.Server.Implementations.Persistence
{
@@ -19,13 +22,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
private readonly IItemRepository _itemRepo;
private readonly ILogger _logger;
private readonly IServerConfigurationManager _config;
+ private readonly IFileSystem _fileSystem;
- public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config)
+ public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
_itemRepo = itemRepo;
_logger = logger;
_config = config;
+ _fileSystem = fileSystem;
}
public string Name
@@ -46,15 +51,18 @@ namespace MediaBrowser.Server.Implementations.Persistence
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
var innerProgress = new ActionableProgress<double>();
- innerProgress.RegisterAction(p => progress.Report(.95 * p));
+ innerProgress.RegisterAction(p => progress.Report(.4 * p));
await UpdateToLatestSchema(cancellationToken, innerProgress).ConfigureAwait(false);
innerProgress = new ActionableProgress<double>();
- innerProgress.RegisterAction(p => progress.Report(95 + (.05 * p)));
-
- //await CleanDeadItems(cancellationToken, innerProgress).ConfigureAwait(false);
+ innerProgress.RegisterAction(p => progress.Report(40 + (.05 * p)));
+ await CleanDeadItems(cancellationToken, innerProgress).ConfigureAwait(false);
+ progress.Report(45);
+ innerProgress = new ActionableProgress<double>();
+ innerProgress.RegisterAction(p => progress.Report(45 + (.55 * p)));
+ await CleanDeletedItems(cancellationToken, innerProgress).ConfigureAwait(false);
progress.Report(100);
}
@@ -77,6 +85,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
cancellationToken.ThrowIfCancellationRequested();
+ if (itemId == Guid.Empty)
+ {
+ // Somehow some invalid data got into the db. It probably predates the boundary checking
+ continue;
+ }
+
var item = _libraryManager.GetItemById(itemId);
if (item != null)
@@ -147,11 +161,60 @@ namespace MediaBrowser.Server.Implementations.Persistence
progress.Report(100);
}
+ private async Task CleanDeletedItems(CancellationToken cancellationToken, IProgress<double> progress)
+ {
+ var result = _itemRepo.GetItemIdsWithPath(new InternalItemsQuery
+ {
+ IsOffline = false,
+ LocationType = 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 }
+ });
+
+ var numComplete = 0;
+ var numItems = result.Items.Length;
+
+ foreach (var item in result.Items)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var path = item.Item2;
+
+ try
+ {
+ if (!_fileSystem.FileExists(path) && !_fileSystem.DirectoryExists(path))
+ {
+ var libraryItem = _libraryManager.GetItemById(item.Item1);
+
+ await _libraryManager.DeleteItem(libraryItem, new DeleteOptions
+ {
+ DeleteFileLocation = 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);
+ }
+ }
+
public IEnumerable<ITaskTrigger> GetDefaultTriggers()
{
return new ITaskTrigger[]
{
- new IntervalTrigger{ Interval = TimeSpan.FromDays(1)}
+ new IntervalTrigger{ Interval = TimeSpan.FromHours(6)}
};
}
}
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
index 00ebf7ea6..3c06973b4 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
@@ -72,7 +72,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
private IDbCommand _deletePeopleCommand;
private IDbCommand _savePersonCommand;
- private const int LatestSchemaVersion = 6;
+ private const int LatestSchemaVersion = 7;
/// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
@@ -175,6 +175,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.AddColumn(_logger, "TypedBaseItems", "ForcedSortName", "Text");
_connection.AddColumn(_logger, "TypedBaseItems", "IsOffline", "BIT");
+ _connection.AddColumn(_logger, "TypedBaseItems", "LocationType", "Text");
PrepareStatements();
@@ -187,11 +188,21 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// </summary>
private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
- private string[] _retriveItemColumns =
+ private readonly string[] _retriveItemColumns =
{
"type",
"data",
- "IsOffline"
+ "StartDate",
+ "EndDate",
+ "IsOffline",
+ "ChannelId",
+ "IsMovie",
+ "IsSports",
+ "IsKids",
+ "CommunityRating",
+ "CustomRating",
+ "IndexNumber",
+ "IsLocked"
};
/// <summary>
@@ -235,7 +246,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
"DateCreated",
"DateModified",
"ForcedSortName",
- "IsOffline"
+ "IsOffline",
+ "LocationType"
};
_saveItemCommand = _connection.CreateCommand();
_saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
@@ -405,6 +417,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveItemCommand.GetParameter(index++).Value = item.ForcedSortName;
_saveItemCommand.GetParameter(index++).Value = item.IsOffline;
+ _saveItemCommand.GetParameter(index++).Value = item.LocationType.ToString();
_saveItemCommand.Transaction = transaction;
@@ -511,7 +524,65 @@ namespace MediaBrowser.Server.Implementations.Persistence
if (!reader.IsDBNull(2))
{
- item.IsOffline = reader.GetBoolean(2);
+ var hasStartDate = item as IHasStartDate;
+ if (hasStartDate != null)
+ {
+ hasStartDate.StartDate = reader.GetDateTime(2).ToUniversalTime();
+ }
+ }
+
+ if (!reader.IsDBNull(3))
+ {
+ item.EndDate = reader.GetDateTime(3).ToUniversalTime();
+ }
+
+ if (!reader.IsDBNull(4))
+ {
+ item.IsOffline = reader.GetBoolean(4);
+ }
+
+ if (!reader.IsDBNull(5))
+ {
+ item.ChannelId = reader.GetString(5);
+ }
+
+ var hasProgramAttributes = item as IHasProgramAttributes;
+ if (hasProgramAttributes != null)
+ {
+ if (!reader.IsDBNull(6))
+ {
+ hasProgramAttributes.IsMovie = reader.GetBoolean(6);
+ }
+
+ if (!reader.IsDBNull(7))
+ {
+ hasProgramAttributes.IsSports = reader.GetBoolean(7);
+ }
+
+ if (!reader.IsDBNull(8))
+ {
+ hasProgramAttributes.IsKids = reader.GetBoolean(8);
+ }
+ }
+
+ if (!reader.IsDBNull(9))
+ {
+ item.CommunityRating = reader.GetFloat(9);
+ }
+
+ if (!reader.IsDBNull(10))
+ {
+ item.CustomRating = reader.GetString(10);
+ }
+
+ if (!reader.IsDBNull(11))
+ {
+ item.IndexNumber = reader.GetInt32(11);
+ }
+
+ if (!reader.IsDBNull(12))
+ {
+ item.IsLocked = reader.GetBoolean(12);
}
return item;
@@ -882,6 +953,75 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
+ public QueryResult<Tuple<Guid, string>> GetItemIdsWithPath(InternalItemsQuery query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ CheckDisposed();
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "select guid,path from TypedBaseItems";
+
+ var whereClauses = GetWhereClauses(query, cmd, false);
+
+ var whereTextWithoutPaging = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ whereClauses = GetWhereClauses(query, cmd, true);
+
+ var whereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ cmd.CommandText += whereText;
+
+ cmd.CommandText += GetOrderByText(query);
+
+ if (query.Limit.HasValue)
+ {
+ cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ cmd.CommandText += "; select count (guid) from TypedBaseItems" + whereTextWithoutPaging;
+
+ var list = new List<Tuple<Guid, string>>();
+ var count = 0;
+
+ _logger.Debug(cmd.CommandText);
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
+ {
+ while (reader.Read())
+ {
+ var id = reader.GetGuid(0);
+ string path = null;
+
+ if (!reader.IsDBNull(1))
+ {
+ path = reader.GetString(1);
+ }
+ list.Add(new Tuple<Guid, string>(id, path));
+ }
+
+ if (reader.NextResult() && reader.Read())
+ {
+ count = reader.GetInt32(0);
+ }
+ }
+
+ return new QueryResult<Tuple<Guid, string>>()
+ {
+ Items = list.ToArray(),
+ TotalRecordCount = count
+ };
+ }
+ }
+
public QueryResult<Guid> GetItemIds(InternalItemsQuery query)
{
if (query == null)
@@ -960,6 +1100,16 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
cmd.Parameters.Add(cmd, "@SchemaVersion", DbType.Int32).Value = LatestSchemaVersion;
}
+ if (query.IsOffline.HasValue)
+ {
+ whereClauses.Add("IsOffline=@IsOffline");
+ cmd.Parameters.Add(cmd, "@IsOffline", DbType.Boolean).Value = query.IsOffline;
+ }
+ if (query.LocationType.HasValue)
+ {
+ whereClauses.Add("LocationType=@LocationType");
+ cmd.Parameters.Add(cmd, "@LocationType", DbType.String).Value = query.LocationType.Value;
+ }
if (query.IsMovie.HasValue)
{
whereClauses.Add("IsMovie=@IsMovie");
diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs
index 4b7e1c3a7..bd5c571fe 100644
--- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs
@@ -92,7 +92,7 @@ namespace MediaBrowser.Server.Implementations.Photos
CancellationToken cancellationToken)
{
var outputPath = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid() + ".png");
- Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+ FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
var imageCreated = await CreateImage(item, itemsWithImages, outputPath, imageType, 0).ConfigureAwait(false);
if (!imageCreated)
@@ -145,7 +145,7 @@ namespace MediaBrowser.Server.Implementations.Photos
private Task<bool> CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height)
{
- Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+ FileSystem.CreateDirectory(Path.GetDirectoryName(outputPath));
var options = new ImageCollageOptions
{
diff --git a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
index 3ec41b6dc..0daef052d 100644
--- a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Controller.Playlists;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.Playlists
{
@@ -46,17 +47,19 @@ namespace MediaBrowser.Server.Implementations.Playlists
public class PlaylistsDynamicFolder : IVirtualFolderCreator
{
private readonly IApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
- public PlaylistsDynamicFolder(IApplicationPaths appPaths)
+ public PlaylistsDynamicFolder(IApplicationPaths appPaths, IFileSystem fileSystem)
{
_appPaths = appPaths;
+ _fileSystem = fileSystem;
}
public BasePluginFolder GetFolder()
{
var path = Path.Combine(_appPaths.DataPath, "playlists");
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
return new PlaylistsFolder
{
diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs
index 857cf743f..53f2211d3 100644
--- a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs
+++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs
@@ -110,7 +110,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
try
{
- Directory.CreateDirectory(path);
+ _fileSystem.CreateDirectory(path);
var playlist = new Playlist
{
@@ -128,7 +128,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
await parentFolder.AddChild(playlist, CancellationToken.None).ConfigureAwait(false);
- await playlist.RefreshMetadata(new MetadataRefreshOptions { ForceSave = true }, CancellationToken.None)
+ await playlist.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) { ForceSave = true }, CancellationToken.None)
.ConfigureAwait(false);
if (options.ItemIdList.Count > 0)
@@ -150,7 +150,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
private string GetTargetPath(string path)
{
- while (Directory.Exists(path))
+ while (_fileSystem.DirectoryExists(path))
{
path += "1";
}
@@ -196,7 +196,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
await playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
- _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions
+ _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
{
ForceSave = true
});
@@ -223,7 +223,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
await playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
- _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions
+ _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(_fileSystem)
{
ForceSave = true
});
diff --git a/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs
index b23aaeeff..f8dc08e26 100644
--- a/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs
+++ b/MediaBrowser.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs
@@ -11,6 +11,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
namespace MediaBrowser.Server.Implementations.ScheduledTasks
{
@@ -39,6 +40,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
private readonly IApplicationPaths _appPaths;
private readonly IEncodingManager _encodingManager;
+ private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="ChapterImagesTask" /> class.
@@ -46,13 +48,14 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
/// <param name="logManager">The log manager.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="itemRepo">The item repo.</param>
- public ChapterImagesTask(ILogManager logManager, ILibraryManager libraryManager, IItemRepository itemRepo, IApplicationPaths appPaths, IEncodingManager encodingManager)
+ public ChapterImagesTask(ILogManager logManager, ILibraryManager libraryManager, IItemRepository itemRepo, IApplicationPaths appPaths, IEncodingManager encodingManager, IFileSystem fileSystem)
{
_logger = logManager.GetLogger(GetType().Name);
_libraryManager = libraryManager;
_itemRepo = itemRepo;
_appPaths = appPaths;
_encodingManager = encodingManager;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -94,7 +97,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
try
{
- previouslyFailedImages = File.ReadAllText(failHistoryPath)
+ previouslyFailedImages = _fileSystem.ReadAllText(failHistoryPath)
.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries)
.ToList();
}
@@ -132,9 +135,9 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks
var parentPath = Path.GetDirectoryName(failHistoryPath);
- Directory.CreateDirectory(parentPath);
+ _fileSystem.CreateDirectory(parentPath);
- File.WriteAllText(failHistoryPath, string.Join("|", previouslyFailedImages.ToArray()));
+ _fileSystem.WriteAllText(failHistoryPath, string.Join("|", previouslyFailedImages.ToArray()));
}
numComplete++;
diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
index 86ef58e42..83dd13c05 100644
--- a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
+++ b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
@@ -147,7 +147,14 @@ namespace MediaBrowser.Server.Implementations.Sync
progress.Report(totalProgress);
});
- await GetItem(provider, dataProvider, target, serverId, serverName, jobItem, innerProgress, cancellationToken).ConfigureAwait(false);
+ try
+ {
+ await GetItem(provider, dataProvider, target, serverId, serverName, jobItem, innerProgress, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error syncing item", ex);
+ }
numComplete++;
startingPercent = numComplete;
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
index 1061a373e..c9099dbe7 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
@@ -702,7 +702,7 @@ namespace MediaBrowser.Server.Implementations.Sync
var path = Path.Combine(temporaryPath, filename);
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
using (var stream = await _subtitleEncoder.GetSubtitles(streamInfo.ItemId, streamInfo.MediaSourceId, subtitleStreamIndex, subtitleStreamInfo.Format, 0, null, cancellationToken).ConfigureAwait(false))
{
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
index 18fcb4e79..15d196877 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
@@ -516,60 +516,25 @@ namespace MediaBrowser.Server.Implementations.Sync
return false;
}
- if (!item.RunTimeTicks.HasValue)
- {
- return false;
- }
-
var video = item as Video;
if (video != null)
{
- if (video.VideoType == VideoType.Iso || video.VideoType == VideoType.HdDvd)
- {
- return false;
- }
-
if (video.IsPlaceHolder)
{
return false;
}
- if (video.IsArchive)
- {
- return false;
- }
-
- if (video.IsStacked)
- {
- return false;
- }
-
if (video.IsShortcut)
{
return false;
}
}
- var game = item as Game;
- if (game != null)
- {
- if (game.IsMultiPart)
- {
- return false;
- }
- }
-
if (item is LiveTvChannel || item is IChannelItem)
{
return false;
}
- // It would be nice to support these later
- if (item is Game || item is Book)
- {
- return false;
- }
-
return true;
}
@@ -997,8 +962,6 @@ namespace MediaBrowser.Server.Implementations.Sync
return false;
}
- // TODO: Make sure it hasn't been deleted
-
return true;
}
diff --git a/MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs b/MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs
deleted file mode 100644
index 2711c08aa..000000000
--- a/MediaBrowser.Server.Implementations/Themes/AppThemeManager.cs
+++ /dev/null
@@ -1,168 +0,0 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Themes;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Themes;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace MediaBrowser.Server.Implementations.Themes
-{
- public class AppThemeManager : IAppThemeManager
- {
- private readonly IServerApplicationPaths _appPaths;
- private readonly IFileSystem _fileSystem;
- private readonly IJsonSerializer _json;
- private readonly ILogger _logger;
-
- private readonly string[] _supportedImageExtensions = { ".png", ".jpg", ".jpeg" };
-
- public AppThemeManager(IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer json, ILogger logger)
- {
- _appPaths = appPaths;
- _fileSystem = fileSystem;
- _json = json;
- _logger = logger;
- }
-
- private string ThemePath
- {
- get
- {
- return Path.Combine(_appPaths.ProgramDataPath, "appthemes");
- }
- }
-
- private string GetThemesPath(string applicationName)
- {
- if (string.IsNullOrWhiteSpace(applicationName))
- {
- throw new ArgumentNullException("applicationName");
- }
-
- // Force everything lowercase for consistency and maximum compatibility with case-sensitive file systems
- var name = _fileSystem.GetValidFilename(applicationName.ToLower());
-
- return Path.Combine(ThemePath, name);
- }
-
- private string GetThemePath(string applicationName, string name)
- {
- if (string.IsNullOrWhiteSpace(name))
- {
- throw new ArgumentNullException("name");
- }
-
- // Force everything lowercase for consistency and maximum compatibility with case-sensitive file systems
- name = _fileSystem.GetValidFilename(name.ToLower());
-
- return Path.Combine(GetThemesPath(applicationName), name);
- }
-
- private string GetImagesPath(string applicationName, string themeName)
- {
- return Path.Combine(GetThemePath(applicationName, themeName), "images");
- }
-
- public IEnumerable<AppThemeInfo> GetThemes(string applicationName)
- {
- var path = GetThemesPath(applicationName);
-
- try
- {
- return Directory
- .EnumerateFiles(path, "*", SearchOption.AllDirectories)
- .Where(i => string.Equals(Path.GetExtension(i), ".json", StringComparison.OrdinalIgnoreCase))
- .Select(i =>
- {
- try
- {
- return _json.DeserializeFromFile<AppThemeInfo>(i);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error deserializing {0}", ex, i);
- return null;
- }
-
- }).Where(i => i != null);
- }
- catch (DirectoryNotFoundException)
- {
- return new List<AppThemeInfo>();
- }
- }
-
- public AppTheme GetTheme(string applicationName, string name)
- {
- var themePath = GetThemePath(applicationName, name);
- var file = Path.Combine(themePath, "theme.json");
-
- var imagesPath = GetImagesPath(applicationName, name);
-
- var theme = _json.DeserializeFromFile<AppTheme>(file);
-
- theme.Images = new DirectoryInfo(imagesPath)
- .EnumerateFiles("*", SearchOption.TopDirectoryOnly)
- .Where(i => _supportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
- .Select(GetThemeImage)
- .ToList();
-
- return theme;
- }
-
- private ThemeImage GetThemeImage(FileInfo file)
- {
- var dateModified = _fileSystem.GetLastWriteTimeUtc(file);
-
- var cacheTag = (file.FullName + dateModified.Ticks).GetMD5().ToString("N");
-
- return new ThemeImage
- {
- CacheTag = cacheTag,
- Name = file.Name
- };
- }
-
- public void SaveTheme(AppTheme theme)
- {
- var themePath = GetThemePath(theme.AppName, theme.Name);
- var file = Path.Combine(themePath, "theme.json");
-
- Directory.CreateDirectory(themePath);
-
- // Clone it so that we don't serialize all the images - they're always dynamic
- var clone = new AppTheme
- {
- AppName = theme.AppName,
- Name = theme.Name,
- Options = theme.Options,
- Images = null
- };
-
- _json.SerializeToFile(clone, file);
- }
-
- public InternalThemeImage GetImageImageInfo(string applicationName, string themeName, string imageName)
- {
- var imagesPath = GetImagesPath(applicationName, themeName);
-
- var file = new DirectoryInfo(imagesPath).EnumerateFiles("*", SearchOption.TopDirectoryOnly)
- .First(i => string.Equals(i.Name, imageName, StringComparison.OrdinalIgnoreCase));
-
- var themeImage = GetThemeImage(file);
-
- return new InternalThemeImage
- {
- CacheTag = themeImage.CacheTag,
- Name = themeImage.Name,
- Path = file.FullName,
- DateModified = _fileSystem.GetLastWriteTimeUtc(file)
- };
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs
index 8321ab952..2f5702983 100644
--- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs
@@ -66,14 +66,14 @@ namespace MediaBrowser.Server.Implementations.UserViews
}
var isUsingCollectionStrip = IsUsingCollectionStrip(view);
- var recursive = isUsingCollectionStrip && !new[] { CollectionType.Playlists, CollectionType.Channels }.Contains(view.ViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
+ var recursive = isUsingCollectionStrip && !new[] { CollectionType.Channels, CollectionType.BoxSets, CollectionType.Playlists }.Contains(view.ViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
var result = await view.GetItems(new InternalItemsQuery
{
User = (view.UserId.HasValue ? _userManager.GetUserById(view.UserId.Value) : null),
CollapseBoxSetItems = false,
Recursive = recursive,
- ExcludeItemTypes = new[] { "UserView", "CollectionFolder", "Playlist" }
+ ExcludeItemTypes = new[] { "UserView", "CollectionFolder" }
}).ConfigureAwait(false);
@@ -147,7 +147,14 @@ namespace MediaBrowser.Server.Implementations.UserViews
{
CollectionType.Movies,
CollectionType.TvShows,
- CollectionType.Music
+ CollectionType.Music,
+ CollectionType.Games,
+ CollectionType.Books,
+ CollectionType.MusicVideos,
+ CollectionType.HomeVideos,
+ CollectionType.BoxSets,
+ CollectionType.Playlists,
+ CollectionType.Photos
};
return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty);
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index 92388c99e..758791868 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -3,7 +3,7 @@
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
<package id="MediaBrowser.Naming" version="1.0.0.37" targetFramework="net45" />
<package id="Mono.Nat" version="1.2.24.0" targetFramework="net45" />
- <package id="morelinq" version="1.1.0" targetFramework="net45" />
+ <package id="morelinq" version="1.1.1" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
<package id="SocketHttpListener" version="1.0.0.7" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Server.Mac.userprefs b/MediaBrowser.Server.Mac.userprefs
index b5f227685..cd108e550 100644
--- a/MediaBrowser.Server.Mac.userprefs
+++ b/MediaBrowser.Server.Mac.userprefs
@@ -1,25 +1,6 @@
<Properties>
<MonoDevelop.Ide.Workspace ActiveConfiguration="Release" />
- <MonoDevelop.Ide.Workbench ActiveDocument="MediaBrowser.Common/Properties/AssemblyInfo.cs">
- <Files>
- <File FileName="MediaBrowser.Server.Mac/ImageMagickSharp.dll.config" Line="1" Column="1" />
- <File FileName="MediaBrowser.Server.Startup.Common/ApplicationHost.cs" Line="1" Column="18" />
- <File FileName="MediaBrowser.Api/ConnectService.cs" Line="7" Column="22" />
- <File FileName="MediaBrowser.Server.Mac/AppController.cs" Line="22" Column="1" />
- <File FileName="MediaBrowser.Server.Mac/AppDelegate.cs" Line="24" Column="1" />
- <File FileName="MediaBrowser.Server.Mac/Main.cs" Line="60" Column="4" />
- <File FileName="SharedVersion.cs" Line="1" Column="1" />
- <File FileName="MediaBrowser.Common/Properties/AssemblyInfo.cs" Line="9" Column="12" />
- </Files>
- <Pads>
- <Pad Id="ProjectPad">
- <State expanded="True">
- <Node name="Emby.Server.Mac" selected="True" />
- <Node name="OpenSubtitlesHandler" expanded="True" />
- </State>
- </Pad>
- </Pads>
- </MonoDevelop.Ide.Workbench>
+ <MonoDevelop.Ide.Workbench />
<MonoDevelop.Ide.DebuggingService.Breakpoints>
<BreakpointStore>
<Breakpoint file="/Users/luke/MediaBrowser/MediaBrowser.Common.Implementations/BaseApplicationPaths.cs" line="233" column="1" />
diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
index 9ecd0764a..c38c81866 100644
--- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
+++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
@@ -42,7 +42,6 @@ using MediaBrowser.Controller.Social;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Controller.Sync;
-using MediaBrowser.Controller.Themes;
using MediaBrowser.Controller.TV;
using MediaBrowser.Dlna;
using MediaBrowser.Dlna.ConnectionManager;
@@ -87,7 +86,6 @@ using MediaBrowser.Server.Implementations.ServerManager;
using MediaBrowser.Server.Implementations.Session;
using MediaBrowser.Server.Implementations.Social;
using MediaBrowser.Server.Implementations.Sync;
-using MediaBrowser.Server.Implementations.Themes;
using MediaBrowser.Server.Implementations.TV;
using MediaBrowser.Server.Startup.Common.FFMpeg;
using MediaBrowser.Server.Startup.Common.Migrations;
@@ -124,7 +122,7 @@ namespace MediaBrowser.Server.Startup.Common
/// <returns>IConfigurationManager.</returns>
protected override IConfigurationManager GetConfigurationManager()
{
- return new ServerConfigurationManager(ApplicationPaths, LogManager, XmlSerializer);
+ return new ServerConfigurationManager(ApplicationPaths, LogManager, XmlSerializer, FileSystemManager);
}
/// <summary>
@@ -314,6 +312,7 @@ namespace MediaBrowser.Server.Startup.Common
await base.RunStartupTasks().ConfigureAwait(false);
Logger.Info("Core startup complete");
+ HttpServer.GlobalResponse = null;
Parallel.ForEach(GetExports<IServerEntryPoint>(), entryPoint =>
{
@@ -434,6 +433,7 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
HttpServer = ServerFactory.CreateServer(this, LogManager, ServerConfigurationManager, "Emby", "web/index.html");
+ HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading");
RegisterSingleInstance(HttpServer, false);
progress.Report(10);
@@ -458,7 +458,7 @@ namespace MediaBrowser.Server.Startup.Common
var encryptionManager = new EncryptionManager();
RegisterSingleInstance<IEncryptionManager>(encryptionManager);
- ConnectManager = new ConnectManager(LogManager.GetLogger("Connect"), ApplicationPaths, JsonSerializer, encryptionManager, HttpClient, this, ServerConfigurationManager, UserManager, ProviderManager, SecurityManager);
+ ConnectManager = new ConnectManager(LogManager.GetLogger("Connect"), ApplicationPaths, JsonSerializer, encryptionManager, HttpClient, this, ServerConfigurationManager, UserManager, ProviderManager, SecurityManager, FileSystemManager);
RegisterSingleInstance(ConnectManager);
DeviceManager = new DeviceManager(new DeviceRepository(ApplicationPaths, JsonSerializer, LogManager.GetLogger("DeviceManager"), FileSystemManager), UserManager, FileSystemManager, LibraryMonitor, ConfigurationManager, LogManager.GetLogger("DeviceManager"), NetworkManager);
@@ -475,15 +475,12 @@ namespace MediaBrowser.Server.Startup.Common
ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, LogManager.GetLogger("ChannelManager"), ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, LocalizationManager, HttpClient);
RegisterSingleInstance(ChannelManager);
- MediaSourceManager = new MediaSourceManager(ItemRepository, UserManager, LibraryManager, LogManager.GetLogger("MediaSourceManager"), JsonSerializer);
+ MediaSourceManager = new MediaSourceManager(ItemRepository, UserManager, LibraryManager, LogManager.GetLogger("MediaSourceManager"), JsonSerializer, FileSystemManager);
RegisterSingleInstance(MediaSourceManager);
SessionManager = new SessionManager(UserDataManager, LogManager.GetLogger("SessionManager"), UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager, MediaSourceManager);
RegisterSingleInstance(SessionManager);
- var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger);
- RegisterSingleInstance<IAppThemeManager>(appThemeManager);
-
var dlnaManager = new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LogManager.GetLogger("Dlna"), JsonSerializer, this);
RegisterSingleInstance<IDlnaManager>(dlnaManager);
@@ -573,7 +570,7 @@ namespace MediaBrowser.Server.Startup.Common
{
try
{
- return new ImageMagickEncoder(LogManager.GetLogger("ImageMagick"), ApplicationPaths, HttpClient);
+ return new ImageMagickEncoder(LogManager.GetLogger("ImageMagick"), ApplicationPaths, HttpClient, FileSystemManager);
}
catch (Exception ex)
{
@@ -598,9 +595,7 @@ namespace MediaBrowser.Server.Startup.Common
var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment)
.GetFFMpegInfo(NativeApp.Environment, _startupOptions, progress).ConfigureAwait(false);
- new FFmpegValidator(Logger, ApplicationPaths).Validate(info);
-
- MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"),
+ var mediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"),
JsonSerializer,
info.EncoderPath,
info.ProbePath,
@@ -614,7 +609,17 @@ namespace MediaBrowser.Server.Startup.Common
SessionManager,
() => SubtitleEncoder,
() => MediaSourceManager);
+
+ MediaEncoder = mediaEncoder;
RegisterSingleInstance(MediaEncoder);
+
+ Task.Run(() =>
+ {
+ var result = new FFmpegValidator(Logger, ApplicationPaths, FileSystemManager).Validate(info);
+
+ mediaEncoder.SetAvailableDecoders(result.Item1);
+ mediaEncoder.SetAvailableEncoders(result.Item2);
+ });
}
/// <summary>
@@ -793,7 +798,7 @@ namespace MediaBrowser.Server.Startup.Common
SessionManager.AddParts(GetExports<ISessionControllerFactory>());
- ChannelManager.AddParts(GetExports<IChannel>(), GetExports<IChannelFactory>());
+ ChannelManager.AddParts(GetExports<IChannel>());
MediaSourceManager.AddParts(GetExports<IMediaSourceProvider>());
@@ -851,9 +856,9 @@ namespace MediaBrowser.Server.Startup.Common
if (generateCertificate)
{
- if (!File.Exists(certPath))
+ if (!FileSystemManager.FileExists(certPath))
{
- Directory.CreateDirectory(Path.GetDirectoryName(certPath));
+ FileSystemManager.CreateDirectory(Path.GetDirectoryName(certPath));
try
{
diff --git a/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs b/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs
index 3eeb072a8..a4504f25a 100644
--- a/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs
+++ b/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs
@@ -24,15 +24,6 @@ namespace MediaBrowser.Server.Startup.Common.Browser
}
/// <summary>
- /// Opens the github.
- /// </summary>
- /// <param name="logger">The logger.</param>
- public static void OpenGithub(ILogger logger)
- {
- OpenUrl("https://github.com/MediaBrowser/MediaBrowser", logger);
- }
-
- /// <summary>
/// Opens the community.
/// </summary>
/// <param name="logger">The logger.</param>
@@ -62,18 +53,6 @@ namespace MediaBrowser.Server.Startup.Common.Browser
}
/// <summary>
- /// Opens the swagger.
- /// </summary>
- /// <param name="appHost">The app host.</param>
- /// <param name="logger">The logger.</param>
- public static void OpenSwagger(IServerApplicationHost appHost, ILogger logger)
- {
- var url = appHost.GetLocalApiUrl("localhost") + "/swagger-ui/index.html";
-
- OpenUrl(url, logger);
- }
-
- /// <summary>
/// Opens the URL.
/// </summary>
/// <param name="url">The URL.</param>
diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs
index 2910479ef..42fc73488 100644
--- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs
+++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs
@@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case OperatingSystem.Linux:
info.ArchiveType = "7z";
- info.Version = "20150717";
+ info.Version = "20150917";
break;
case OperatingSystem.Osx:
@@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
switch (environment.SystemArchitecture)
{
case Architecture.X86_X64:
- info.Version = "20150827";
+ info.Version = "20150917";
break;
case Architecture.X86:
info.Version = "20150110";
@@ -54,7 +54,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
info.FFMpegFilename = "ffmpeg.exe";
info.FFProbeFilename = "ffprobe.exe";
- info.Version = "20150717";
+ info.Version = "20150918";
info.ArchiveType = "7z";
switch (environment.SystemArchitecture)
@@ -83,14 +83,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case Architecture.X86_X64:
return new[]
{
- "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20150717-git-8250943-win64-static.7z",
- "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150901-git-b54e03c-win64-static.7z"
+ "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150918-win64.7z",
+ "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20150916-git-cbbd906-win64-static.7z"
};
case Architecture.X86:
return new[]
{
- "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20150717-git-8250943-win32-static.7z",
- "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150901-git-b54e03c-win32-static.7z"
+ "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20150918-win32.7z",
+ "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20150916-git-cbbd906-win32-static.7z"
};
}
break;
@@ -102,7 +102,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case Architecture.X86_X64:
return new[]
{
- "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.7.2.7z"
+ "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.8.0.7z"
};
case Architecture.X86:
return new[]
@@ -119,12 +119,12 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case Architecture.X86_X64:
return new[]
{
- "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.7.1-64bit-static.7z"
+ "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.8.0-64bit-static.7z"
};
case Architecture.X86:
return new[]
{
- "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.7.1-32bit-static.7z"
+ "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-2.8.0-32bit-static.7z"
};
}
break;
diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs
index fe7cd943a..16864898a 100644
--- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs
+++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs
@@ -78,11 +78,11 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
Version = version
};
- Directory.CreateDirectory(versionedDirectoryPath);
+ _fileSystem.CreateDirectory(versionedDirectoryPath);
var excludeFromDeletions = new List<string> { versionedDirectoryPath };
- if (!File.Exists(info.ProbePath) || !File.Exists(info.EncoderPath))
+ if (!_fileSystem.FileExists(info.ProbePath) || !_fileSystem.FileExists(info.EncoderPath))
{
// ffmpeg not present. See if there's an older version we can start with
var existingVersion = GetExistingVersion(info, rootEncoderPath);
@@ -218,7 +218,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
var tempFolder = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString());
- Directory.CreateDirectory(tempFolder);
+ _fileSystem.CreateDirectory(tempFolder);
try
{
@@ -237,7 +237,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
}))
{
var targetFile = Path.Combine(targetFolder, Path.GetFileName(file));
- File.Copy(file, targetFile, true);
+ _fileSystem.CopyFile(file, targetFile, true);
SetFilePermissions(targetFile);
}
}
@@ -301,13 +301,13 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
{
var fontsDirectory = Path.Combine(targetPath, "fonts");
- Directory.CreateDirectory(fontsDirectory);
+ _fileSystem.CreateDirectory(fontsDirectory);
const string fontFilename = "ARIALUNI.TTF";
var fontFile = Path.Combine(fontsDirectory, fontFilename);
- if (File.Exists(fontFile))
+ if (_fileSystem.FileExists(fontFile))
{
await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
}
@@ -350,7 +350,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
{
try
{
- File.Copy(existingFile, Path.Combine(fontsDirectory, fontFilename), true);
+ _fileSystem.CopyFile(existingFile, Path.Combine(fontsDirectory, fontFilename), true);
return;
}
catch (IOException ex)
@@ -412,7 +412,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
const string fontConfigFilename = "fonts.conf";
var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename);
- if (!File.Exists(fontConfigFile))
+ if (!_fileSystem.FileExists(fontConfigFile))
{
var contents = string.Format("<?xml version=\"1.0\"?><fontconfig><dir>{0}</dir><alias><family>Arial</family><prefer>Arial Unicode MS</prefer></alias></fontconfig>", fontsDirectory);
diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs
index 124a7f74b..d3388f47e 100644
--- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs
+++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs
@@ -6,6 +6,8 @@ using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
+using MediaBrowser.Common.IO;
+using System.Collections.Generic;
namespace MediaBrowser.Server.Startup.Common.FFMpeg
{
@@ -13,78 +15,74 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
{
private readonly ILogger _logger;
private readonly IApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
- public FFmpegValidator(ILogger logger, IApplicationPaths appPaths)
+ public FFmpegValidator(ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem)
{
_logger = logger;
_appPaths = appPaths;
+ _fileSystem = fileSystem;
}
- public void Validate(FFMpegInfo info)
+ public Tuple<List<string>,List<string>> Validate(FFMpegInfo info)
{
_logger.Info("FFMpeg: {0}", info.EncoderPath);
_logger.Info("FFProbe: {0}", info.ProbePath);
- string cacheKey;
+ var decoders = GetDecoders(info.EncoderPath);
+ var encoders = GetEncoders(info.EncoderPath);
- try
- {
- cacheKey = new FileInfo(info.EncoderPath).Length.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N");
- }
- catch (IOException)
- {
- // This could happen if ffmpeg is coming from a Path variable and we don't have the full path
- cacheKey = Guid.NewGuid().ToString("N");
- }
- catch
- {
- cacheKey = Guid.NewGuid().ToString("N");
- }
-
- var cachePath = Path.Combine(_appPaths.CachePath, "1" + cacheKey);
-
- ValidateCodecs(info.EncoderPath, cachePath);
+ return new Tuple<List<string>, List<string>>(decoders, encoders);
}
- private void ValidateCodecs(string ffmpegPath, string cachePath)
+ private List<string> GetDecoders(string ffmpegPath)
{
- string output = null;
+ string output = string.Empty;
try
{
- output = File.ReadAllText(cachePath, Encoding.UTF8);
+ output = GetFFMpegOutput(ffmpegPath, "-decoders");
}
catch
{
-
}
- if (string.IsNullOrWhiteSpace(output))
+ var found = new List<string>();
+ var required = new[]
{
- try
- {
- output = GetFFMpegOutput(ffmpegPath, "-encoders");
- }
- catch
- {
- return;
- }
+ "h264_qsv",
+ "mpeg2_qsv",
+ "vc1_qsv"
+ };
- try
+ foreach (var codec in required)
+ {
+ var srch = " " + codec + " ";
+
+ if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1)
{
- Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
- File.WriteAllText(cachePath, output, Encoding.UTF8);
+ _logger.Warn("ffmpeg is missing decoder " + codec);
}
- catch
+ else
{
-
+ found.Add(codec);
}
}
- ValidateCodecsFromOutput(output);
+ return found;
}
- private void ValidateCodecsFromOutput(string output)
+ private List<string> GetEncoders(string ffmpegPath)
{
+ string output = null;
+ try
+ {
+ output = GetFFMpegOutput(ffmpegPath, "-encoders");
+ }
+ catch
+ {
+ }
+
+ var found = new List<string>();
var required = new[]
{
"libx264",
@@ -100,16 +98,21 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
"srt"
};
- foreach (var encoder in required)
+ foreach (var codec in required)
{
- var srch = " " + encoder + " ";
+ var srch = " " + codec + " ";
if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1)
{
- _logger.Error("ffmpeg is missing encoder " + encoder);
- //throw new ArgumentException("ffmpeg is missing encoder " + encoder);
+ _logger.Warn("ffmpeg is missing encoder " + codec);
+ }
+ else
+ {
+ found.Add(codec);
}
}
+
+ return found;
}
private string GetFFMpegOutput(string path, string arguments)
diff --git a/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs b/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs
index cb566d6cf..1dfe4c0b5 100644
--- a/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs
+++ b/MediaBrowser.Server.Startup.Common/Migrations/MigrateUserFolders.cs
@@ -23,7 +23,8 @@ namespace MediaBrowser.Server.Startup.Common.Migrations
{
var rootPath = _appPaths.RootFolderPath;
- var folders = new DirectoryInfo(rootPath).EnumerateDirectories("*", SearchOption.TopDirectoryOnly).Where(i => !string.Equals(i.Name, "default", StringComparison.OrdinalIgnoreCase))
+ var folders = _fileSystem.GetDirectories(rootPath)
+ .Where(i => !string.Equals(i.Name, "default", StringComparison.OrdinalIgnoreCase))
.ToList();
foreach (var folder in folders)
diff --git a/MediaBrowser.Server.Startup.Common/UnhandledExceptionWriter.cs b/MediaBrowser.Server.Startup.Common/UnhandledExceptionWriter.cs
index 96c24eaab..804533b9d 100644
--- a/MediaBrowser.Server.Startup.Common/UnhandledExceptionWriter.cs
+++ b/MediaBrowser.Server.Startup.Common/UnhandledExceptionWriter.cs
@@ -25,7 +25,7 @@ namespace MediaBrowser.Server.Startup.Common
_logManager.Flush();
var path = Path.Combine(_appPaths.LogDirectoryPath, "unhandled_" + Guid.NewGuid() + ".txt");
- Directory.CreateDirectory(Path.GetDirectoryName(path));
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
var builder = LogHelper.GetLogMessage(ex);
@@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Startup.Common
Console.WriteLine("UnhandledException");
Console.WriteLine(builder.ToString());
- File.WriteAllText(path, builder.ToString());
+ File.WriteAllText(path, builder.ToString());
}
}
}
diff --git a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
index 725720731..3501c8c27 100644
--- a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
+++ b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
@@ -21,9 +21,6 @@ namespace MediaBrowser.ServerApplication
private ToolStripMenuItem cmdRestart;
private ToolStripSeparator toolStripSeparator1;
private ToolStripMenuItem cmdCommunity;
- private ToolStripMenuItem cmdApiDocs;
- private ToolStripMenuItem cmdSwagger;
- private ToolStripMenuItem cmdGtihub;
private readonly ILogger _logger;
private readonly IServerApplicationHost _appHost;
@@ -66,9 +63,6 @@ namespace MediaBrowser.ServerApplication
toolStripSeparator2 = new ToolStripSeparator();
cmdConfigure = new ToolStripMenuItem();
cmdBrowse = new ToolStripMenuItem();
- cmdApiDocs = new ToolStripMenuItem();
- cmdSwagger = new ToolStripMenuItem();
- cmdGtihub = new ToolStripMenuItem();
//
// notifyIcon1
@@ -86,7 +80,6 @@ namespace MediaBrowser.ServerApplication
toolStripSeparator2,
cmdRestart,
toolStripSeparator1,
- cmdApiDocs,
cmdCommunity,
cmdExit});
contextMenuStrip1.Name = "contextMenuStrip1";
@@ -128,24 +121,6 @@ namespace MediaBrowser.ServerApplication
//
cmdBrowse.Name = "cmdBrowse";
cmdBrowse.Size = new System.Drawing.Size(208, 22);
- //
- // cmdApiDocs
- //
- cmdApiDocs.DropDownItems.AddRange(new ToolStripItem[] {
- cmdSwagger,
- cmdGtihub});
- cmdApiDocs.Name = "cmdApiDocs";
- cmdApiDocs.Size = new System.Drawing.Size(208, 22);
- //
- // cmdSwagger
- //
- cmdSwagger.Name = "cmdSwagger";
- cmdSwagger.Size = new System.Drawing.Size(136, 22);
- //
- // cmdGtihub
- //
- cmdGtihub.Name = "cmdGtihub";
- cmdGtihub.Size = new System.Drawing.Size(136, 22);
cmdExit.Click += cmdExit_Click;
cmdRestart.Click += cmdRestart_Click;
@@ -153,9 +128,6 @@ namespace MediaBrowser.ServerApplication
cmdCommunity.Click += cmdCommunity_Click;
cmdBrowse.Click += cmdBrowse_Click;
- cmdSwagger.Click += cmdSwagger_Click;
- cmdGtihub.Click += cmdGtihub_Click;
-
_configurationManager.ConfigurationUpdated += Instance_ConfigurationUpdated;
LocalizeText();
@@ -181,9 +153,6 @@ namespace MediaBrowser.ServerApplication
cmdExit.Text = _localization.GetLocalizedString("LabelExit");
cmdCommunity.Text = _localization.GetLocalizedString("LabelVisitCommunity");
- cmdGtihub.Text = _localization.GetLocalizedString("LabelGithub");
- cmdSwagger.Text = _localization.GetLocalizedString("LabelApiDocumentation");
- cmdApiDocs.Text = _localization.GetLocalizedString("LabelDeveloperResources");
cmdBrowse.Text = _localization.GetLocalizedString("LabelBrowseLibrary");
cmdConfigure.Text = _localization.GetLocalizedString("LabelConfigureServer");
cmdRestart.Text = _localization.GetLocalizedString("LabelRestartServer");
@@ -229,16 +198,6 @@ namespace MediaBrowser.ServerApplication
_appHost.Shutdown();
}
- void cmdGtihub_Click(object sender, EventArgs e)
- {
- BrowserLauncher.OpenGithub(_logger);
- }
-
- void cmdSwagger_Click(object sender, EventArgs e)
- {
- BrowserLauncher.OpenSwagger(_appHost, _logger);
- }
-
~ServerNotifyIcon()
{
Dispose();
diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/unit.srt b/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/unit.srt
index 5f6e5636e..1ce811bcb 100644
--- a/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/unit.srt
+++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/unit.srt
@@ -35,7 +35,7 @@ Unclosed but <b>supported HTML tags are left in, {\i1} SSA italics aren't
9
00:00:36,000 --> 00:00:36,999
-Multiple {\pos(142,120)\b1}SSA tags are stripped
+Multiple {\bord-3.7\clip(1,m 50 0 b 100 0 100 100 50 100 b 0 100 0 0 50 0)\pos(142,120)\t(0,500,\fscx100\fscy100)\b1\c&H000000&}SSA tags are stripped
10
00:00:37,000 --> 00:00:37,999
diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs
index 69c4417cb..c06f845f1 100644
--- a/MediaBrowser.WebDashboard/Api/DashboardService.cs
+++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs
@@ -274,8 +274,8 @@ namespace MediaBrowser.WebDashboard.Api
private void CopyFile(string src, string dst)
{
- Directory.CreateDirectory(Path.GetDirectoryName(dst));
- File.Copy(src, dst, true);
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dst));
+ _fileSystem.CopyFile(src, dst, true);
}
public async Task<object> Get(GetDashboardPackage request)
@@ -306,17 +306,17 @@ namespace MediaBrowser.WebDashboard.Api
{
// Overwrite certain files with cordova specific versions
var cordovaVersion = Path.Combine(path, "cordova", "registrationservices.js");
- File.Copy(cordovaVersion, Path.Combine(path, "scripts", "registrationservices.js"), true);
- File.Delete(cordovaVersion);
+ _fileSystem.CopyFile(cordovaVersion, Path.Combine(path, "scripts", "registrationservices.js"), true);
+ _fileSystem.DeleteFile(cordovaVersion);
// Delete things that are unneeded in an attempt to keep the output as trim as possible
- Directory.Delete(Path.Combine(path, "css", "images", "tour"), true);
- Directory.Delete(Path.Combine(path, "apiclient", "alt"), true);
+ _fileSystem.DeleteDirectory(Path.Combine(path, "css", "images", "tour"), true);
+ _fileSystem.DeleteDirectory(Path.Combine(path, "apiclient", "alt"), true);
- File.Delete(Path.Combine(path, "thirdparty", "jquerymobile-1.4.5", "jquery.mobile-1.4.5.min.map"));
+ _fileSystem.DeleteFile(Path.Combine(path, "thirdparty", "jquerymobile-1.4.5", "jquery.mobile-1.4.5.min.map"));
- Directory.Delete(Path.Combine(path, "bower_components"), true);
- Directory.Delete(Path.Combine(path, "thirdparty", "viblast"), true);
+ _fileSystem.DeleteDirectory(Path.Combine(path, "bower_components"), true);
+ _fileSystem.DeleteDirectory(Path.Combine(path, "thirdparty", "viblast"), true);
// But we do need this
CopyFile(Path.Combine(creator.DashboardUIPath, "bower_components", "webcomponentsjs", "webcomponents-lite.js"), Path.Combine(path, "bower_components", "webcomponentsjs", "webcomponents-lite.js"));
@@ -355,7 +355,7 @@ namespace MediaBrowser.WebDashboard.Api
{
try
{
- var text = File.ReadAllText(file, Encoding.UTF8);
+ var text = _fileSystem.ReadAllText(file, Encoding.UTF8);
var result = new KristensenCssMinifier().Minify(text, false, Encoding.UTF8);
@@ -366,7 +366,7 @@ namespace MediaBrowser.WebDashboard.Api
else
{
text = result.MinifiedContent;
- File.WriteAllText(file, text, Encoding.UTF8);
+ _fileSystem.WriteAllText(file, text, Encoding.UTF8);
}
}
catch (Exception ex)
@@ -382,7 +382,7 @@ namespace MediaBrowser.WebDashboard.Api
{
try
{
- var text = File.ReadAllText(file, Encoding.UTF8);
+ var text = _fileSystem.ReadAllText(file, Encoding.UTF8);
var result = new CrockfordJsMinifier().Minify(text, false, Encoding.UTF8);
@@ -393,7 +393,7 @@ namespace MediaBrowser.WebDashboard.Api
else
{
text = result.MinifiedContent;
- File.WriteAllText(file, text, Encoding.UTF8);
+ _fileSystem.WriteAllText(file, text, Encoding.UTF8);
}
}
catch (Exception ex)
@@ -422,7 +422,7 @@ namespace MediaBrowser.WebDashboard.Api
foreach (var file in excludeFiles)
{
- File.Delete(Path.Combine(destination, file));
+ _fileSystem.DeleteFile(Path.Combine(destination, file));
}
}
@@ -449,17 +449,17 @@ namespace MediaBrowser.WebDashboard.Api
private void CopyDirectory(string source, string destination)
{
- Directory.CreateDirectory(destination);
+ _fileSystem.CreateDirectory(destination);
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(source, "*",
SearchOption.AllDirectories))
- Directory.CreateDirectory(dirPath.Replace(source, destination));
+ _fileSystem.CreateDirectory(dirPath.Replace(source, destination));
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(source, "*.*",
SearchOption.AllDirectories))
- File.Copy(newPath, newPath.Replace(source, destination), true);
+ _fileSystem.CopyFile(newPath, newPath.Replace(source, destination), true);
}
}
diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
index 48ad62bd4..6dac90c1f 100644
--- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs
+++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
@@ -521,7 +521,6 @@ namespace MediaBrowser.WebDashboard.Api
"thirdparty/jquery.unveil-custom.js",
"apiclient/logger.js",
"apiclient/md5.js",
- "apiclient/sha1.js",
"apiclient/store.js",
"apiclient/device.js",
"apiclient/credentials.js",
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 8abd591e5..233a1f3ba 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -57,9 +57,8 @@
<Reference Include="ServiceStack.Interfaces">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference>
- <Reference Include="WebMarkupMin.Core, Version=0.9.12.0, Culture=neutral, PublicKeyToken=99472178d266584b, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\WebMarkupMin.Core.0.9.12\lib\net40\WebMarkupMin.Core.dll</HintPath>
+ <Reference Include="WebMarkupMin.Core">
+ <HintPath>..\packages\WebMarkupMin.Core.1.0.0\lib\net40\WebMarkupMin.Core.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -87,6 +86,24 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
+ <Content Include="dashboard-ui\apiclient\sync\contentuploader.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\apiclient\fileupload.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\apiclient\sync\mediasync.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\apiclient\sync\multiserversync.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\apiclient\sync\offlineusersync.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\apiclient\sync\serversync.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\bower_components\fastclick\lib\fastclick.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -144,18 +161,48 @@
<Content Include="dashboard-ui\bower_components\webcomponentsjs\webcomponents.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\components\imagedownloader\imagedownloader.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\components\imagedownloader\imagedownloader.template.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\components\imageuploader\imageuploader.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\components\imageuploader\imageuploader.template.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\components\paperdialoghelper.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\cordova\android\localsync.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\cordova\android\logging.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\cordova\fileupload.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\cordova\ios\vlcplayer.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\cordova\localassetmanager.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\cordova\searchmenu.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\cordova\sharingwidget.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\images\ani_equalizer_black.gif">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\ani_equalizer_white.gif">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\css\images\clients\androidtv-tile.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -192,6 +239,9 @@
<Content Include="dashboard-ui\css\nowplayingbar.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\components\imageeditor\imageeditor.template.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\livetvguideprovider.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -276,6 +326,9 @@
<Content Include="dashboard-ui\shared.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\components\subtitleeditor\subtitleeditor.template.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\themes\android.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -300,9 +353,6 @@
<Content Include="dashboard-ui\cordova\android\appstorage.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\cordova\android\localassetmanager.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\cordova\android\mediasession.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -330,6 +380,33 @@
<Content Include="dashboard-ui\thirdparty\emby-icons.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.checkbox.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.collapsible.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.collapsible.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.controlgroup.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.controlgroup.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.listview.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.listview.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.panel.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.panel.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.popup.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -342,27 +419,21 @@
<Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.slider.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile.custom.icons.css">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jqm.checkbox.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile.custom.js">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile.custom.icons.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile.custom.min.js">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile.custom.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile.custom.structure.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile.custom.structure.min.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile.custom.theme.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile.custom.theme.min.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\thirdparty\paper-button-style.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -398,6 +469,9 @@
<Content Include="dashboard-ui\tvproviders\schedulesdirect.template.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\voice\textprocessor-en-us.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\voice\voice.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -506,9 +580,6 @@
<Content Include="dashboard-ui\apiclient\ajax.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\apiclient\alt\ajax.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\apiclient\alt\bean.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -784,9 +855,6 @@
<Content Include="dashboard-ui\metadatasubtitles.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\musicalbumartists.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\collections.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -958,10 +1026,7 @@
<Content Include="dashboard-ui\scripts\dlnasettings.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\editcollectionitems.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\scripts\edititemsubtitles.js">
+ <Content Include="dashboard-ui\components\subtitleeditor\subtitleeditor.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\encodingsettings.js">
@@ -1087,9 +1152,6 @@
<Content Include="dashboard-ui\scripts\livetvsuggested.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\serversecurity.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\scripts\sync.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1111,9 +1173,6 @@
<Content Include="dashboard-ui\scripts\wizardsettings.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\serversecurity.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\apiclient\connectionmanager.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1756,9 +1815,6 @@
<Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\images\icons-svg\video-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile-1.4.5.min.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\livetv.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1840,19 +1896,7 @@
<Content Include="dashboard-ui\movies.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\musicalbums.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\musicartists.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\musicgenres.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\musicrecommended.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\musicvideos.html">
+ <Content Include="dashboard-ui\music.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\alphapicker.js">
@@ -1861,7 +1905,7 @@
<Content Include="dashboard-ui\scripts\directorybrowser.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\edititemimages.js">
+ <Content Include="dashboard-ui\components\imageeditor\imageeditor.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\edititemmetadata.js">
@@ -1873,9 +1917,6 @@
<Content Include="dashboard-ui\scripts\musicrecommended.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\musicvideos.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\scripts\notifications.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1888,9 +1929,6 @@
<Content Include="dashboard-ui\scripts\tvlatest.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\songs.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\scripts\moviecollections.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -2652,6 +2690,9 @@
<Content Include="dashboard-ui\strings\javascript\zh-TW.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <None Include="dashboard-ui\strings\html\zh-HK.json">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
<None Include="dashboard-ui\thirdparty\fontawesome\css\font-awesome.css.map">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index 48f68789b..cb5a32347 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.249" targetFramework="net45" />
- <package id="WebMarkupMin.Core" version="0.9.12" targetFramework="net45" />
+ <package id="WebMarkupMin.Core" version="1.0.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs
index 49ace7702..ccac720fc 100644
--- a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs
@@ -39,7 +39,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
return false;
}
- return updateType >= MinimumUpdateType || (updateType >= ItemUpdateType.MetadataImport && File.Exists(GetSavePath(item)));
+ return updateType >= MinimumUpdateType || (updateType >= ItemUpdateType.MetadataImport && FileSystem.FileExists(GetSavePath(item)));
}
protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index f92e05492..c172cf40c 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
- <version>3.0.633</version>
+ <version>3.0.634</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,9 +12,9 @@
<description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Emby 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.633" />
+ <dependency id="MediaBrowser.Common" version="3.0.634" />
<dependency id="NLog" version="3.2.1" />
- <dependency id="SimpleInjector" version="2.8.0" />
+ <dependency id="SimpleInjector" version="3.0.5" />
</dependencies>
</metadata>
<files>
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index 04d4deb7c..978661b6e 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.633</version>
+ <version>3.0.634</version>
<title>MediaBrowser.Common</title>
<authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec
index 2a75ac3a8..767117167 100644
--- a/Nuget/MediaBrowser.Model.Signed.nuspec
+++ b/Nuget/MediaBrowser.Model.Signed.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Model.Signed</id>
- <version>3.0.633</version>
+ <version>3.0.634</version>
<title>MediaBrowser.Model - Signed Edition</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 da8309410..29c9509eb 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.633</version>
+ <version>3.0.634</version>
<title>Media Browser.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.633" />
+ <dependency id="MediaBrowser.Common" version="3.0.634" />
<dependency id="Interfaces.IO" version="1.0.0.5" />
</dependencies>
</metadata>
diff --git a/OpenSubtitlesHandler/MovieHasher.cs b/OpenSubtitlesHandler/MovieHasher.cs
index a14bd20f8..8d11d8267 100644
--- a/OpenSubtitlesHandler/MovieHasher.cs
+++ b/OpenSubtitlesHandler/MovieHasher.cs
@@ -9,17 +9,7 @@ namespace OpenSubtitlesHandler
{
public class MovieHasher
{
- public static byte[] ComputeMovieHash(string filename)
- {
- byte[] result;
- using (Stream input = File.OpenRead(filename))
- {
- result = ComputeMovieHash(input);
- }
- return result;
- }
-
- private static byte[] ComputeMovieHash(Stream input)
+ public static byte[] ComputeMovieHash(Stream input)
{
long lhash, streamsize;
streamsize = input.Length;
diff --git a/OpenSubtitlesHandler/Utilities.cs b/OpenSubtitlesHandler/Utilities.cs
index 7f0f93009..4340d4c3f 100644
--- a/OpenSubtitlesHandler/Utilities.cs
+++ b/OpenSubtitlesHandler/Utilities.cs
@@ -44,7 +44,7 @@ namespace OpenSubtitlesHandler
/// <returns>The hash as Hexadecimal string</returns>
public static string ComputeHash(string fileName)
{
- byte[] hash = MovieHasher.ComputeMovieHash(fileName);
+ byte[] hash = MovieHasher.ComputeMovieHash(File.OpenRead(fileName));
return MovieHasher.ToHexadecimal(hash);
}
/// <summary>
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 36853f5e2..3bb5b51cd 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,4 +1,4 @@
using System.Reflection;
-//[assembly: AssemblyVersion("3.0.*")]
-[assembly: AssemblyVersion("3.0.5724.4")]
+[assembly: AssemblyVersion("3.0.*")]
+//[assembly: AssemblyVersion("3.0.5724.4")]