aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke <luke.pulverenti@gmail.com>2017-05-12 14:19:33 -0400
committerGitHub <noreply@github.com>2017-05-12 14:19:33 -0400
commit1a6ee3d48aec8aa592ea2b0aab9560292ce717d6 (patch)
tree558b953b1e01a16bd47d902c841cc747a50e0ae7
parent65db32b1f878cd478e9f4b2b4c988890a7ca47c9 (diff)
parent3cdb75190d457cbb3bed91bf79bfb4816cad29e2 (diff)
Merge pull request #2633 from MediaBrowser/beta
Beta
-rw-r--r--Emby.Common.Implementations/IO/ManagedFileSystem.cs79
-rw-r--r--Emby.Common.Implementations/IO/SharpCifsFileSystem.cs30
-rw-r--r--Emby.Common.Implementations/project.json2
-rw-r--r--Emby.Dlna/DlnaManager.cs5
-rw-r--r--Emby.Dlna/Emby.Dlna.csproj6
-rw-r--r--Emby.Dlna/Profiles/BubbleUpnpProfile.cs146
-rw-r--r--Emby.Dlna/Profiles/DefaultProfile.cs62
-rw-r--r--Emby.Dlna/Profiles/KodiProfile.cs151
-rw-r--r--Emby.Dlna/Profiles/VlcProfile.cs149
-rw-r--r--Emby.Dlna/Profiles/Xml/BubbleUPnp.xml62
-rw-r--r--Emby.Dlna/Profiles/Xml/Default.xml18
-rw-r--r--Emby.Dlna/Profiles/Xml/Denon AVR.xml14
-rw-r--r--Emby.Dlna/Profiles/Xml/DirecTV HD-DVR.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Dish Hopper-Joey.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Kodi.xml62
-rw-r--r--Emby.Dlna/Profiles/Xml/LG Smart TV.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Linksys DMA2100.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/MediaMonkey.xml14
-rw-r--r--Emby.Dlna/Profiles/Xml/Panasonic Viera.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Popcorn Hour.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Samsung Smart TV.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sharp Smart TV.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2014.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2015.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2016.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony Blu-ray Player.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony Bravia (2010).xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony Bravia (2011).xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony Bravia (2012).xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony Bravia (2013).xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony Bravia (2014).xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony PlayStation 3.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Sony PlayStation 4.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Vlc.xml62
-rw-r--r--Emby.Dlna/Profiles/Xml/WDTV Live.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Xbox 360.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Xbox One.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/foobar2000.xml14
-rw-r--r--Emby.Drawing.ImageMagick/ImageMagickEncoder.cs16
-rw-r--r--Emby.Drawing.Net/GDIImageEncoder.cs17
-rw-r--r--Emby.Drawing.Skia/Emby.Drawing.Skia.csproj80
-rw-r--r--Emby.Drawing.Skia/PercentPlayedDrawer.cs31
-rw-r--r--Emby.Drawing.Skia/PlayedIndicatorDrawer.cs120
-rw-r--r--Emby.Drawing.Skia/Properties/AssemblyInfo.cs25
-rw-r--r--Emby.Drawing.Skia/SkiaEncoder.cs387
-rw-r--r--Emby.Drawing.Skia/StripCollageBuilder.cs190
-rw-r--r--Emby.Drawing.Skia/UnplayedCountIndicator.cs68
-rw-r--r--Emby.Drawing.Skia/packages.config4
-rw-r--r--Emby.Drawing/ImageProcessor.cs133
-rw-r--r--Emby.Drawing/NullImageEncoder.cs5
-rw-r--r--Emby.Server.Core/ApplicationHost.cs19
-rw-r--r--Emby.Server.Core/IO/LibraryMonitor.cs2
-rw-r--r--Emby.Server.Core/project.json2
-rw-r--r--Emby.Server.Implementations/Activity/ActivityRepository.cs4
-rw-r--r--Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs4
-rw-r--r--Emby.Server.Implementations/AppBase/ConfigurationHelper.cs2
-rw-r--r--Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs10
-rw-r--r--Emby.Server.Implementations/Data/SqliteExtensions.cs12
-rw-r--r--Emby.Server.Implementations/Data/SqliteFileOrganizationRepository.cs8
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs56
-rw-r--r--Emby.Server.Implementations/Data/SqliteUserDataRepository.cs8
-rw-r--r--Emby.Server.Implementations/Data/SqliteUserRepository.cs6
-rw-r--r--Emby.Server.Implementations/Devices/DeviceManager.cs2
-rw-r--r--Emby.Server.Implementations/Devices/DeviceRepository.cs4
-rw-r--r--Emby.Server.Implementations/Emby.Server.Implementations.csproj2
-rw-r--r--Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs4
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpListenerHost.cs9
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpResultFactory.cs46
-rw-r--r--Emby.Server.Implementations/HttpServer/LoggerUtils.cs20
-rw-r--r--Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs7
-rw-r--r--Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs9
-rw-r--r--Emby.Server.Implementations/IO/FileRefresher.cs10
-rw-r--r--Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs2
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs1
-rw-r--r--Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs2
-rw-r--r--Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs2
-rw-r--r--Emby.Server.Implementations/Library/Validators/GenresValidator.cs2
-rw-r--r--Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs2
-rw-r--r--Emby.Server.Implementations/Library/Validators/StudiosValidator.cs2
-rw-r--r--Emby.Server.Implementations/Library/Validators/YearsPostScanTask.cs4
-rw-r--r--Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs18
-rw-r--r--Emby.Server.Implementations/Security/AuthenticationRepository.cs6
-rw-r--r--Emby.Server.Implementations/Social/SharingRepository.cs6
-rw-r--r--Emby.Server.Implementations/Updates/InstallationManager.cs14
-rw-r--r--Emby.Server.Implementations/packages.config2
-rw-r--r--Emby.Server.sln2
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj4
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs5
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs12
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs2
-rw-r--r--MediaBrowser.Api/Reports/Common/HeaderMetadata.cs3
-rw-r--r--MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs5
-rw-r--r--MediaBrowser.Api/Reports/Data/ReportBuilder.cs13
-rw-r--r--MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs256
-rw-r--r--MediaBrowser.Api/Reports/Stat/ReportStatGroup.cs33
-rw-r--r--MediaBrowser.Api/Reports/Stat/ReportStatItem.cs23
-rw-r--r--MediaBrowser.Api/Reports/Stat/ReportStatResult.cs24
-rw-r--r--MediaBrowser.Controller/Drawing/IImageEncoder.cs8
-rw-r--r--MediaBrowser.Controller/Drawing/IImageProcessor.cs2
-rw-r--r--MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs1
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs37
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs46
-rw-r--r--MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs6
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs5
-rw-r--r--MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs34
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs1
-rw-r--r--MediaBrowser.Model/Drawing/ImageSize.cs6
-rw-r--r--MediaBrowser.Model/IO/IFileSystem.cs47
-rw-r--r--MediaBrowser.Model/Services/IRequest.cs2
-rw-r--r--MediaBrowser.Providers/Manager/ImageSaver.cs27
-rw-r--r--MediaBrowser.Providers/Manager/ProviderUtils.cs15
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbItemProvider.cs19
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbProvider.cs17
-rw-r--r--MediaBrowser.Server.Mac/Emby.Server.Mac.csproj4
-rw-r--r--MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj4
-rw-r--r--MediaBrowser.Server.Mono/packages.config4
-rw-r--r--MediaBrowser.ServerApplication/ImageEncoderHelper.cs10
-rw-r--r--MediaBrowser.ServerApplication/MainStartup.cs126
-rw-r--r--MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj20
-rw-r--r--MediaBrowser.ServerApplication/Native/LoopUtil.cs21
-rw-r--r--MediaBrowser.ServerApplication/packages.config5
-rw-r--r--MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs25
-rw-r--r--MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs13
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs7
-rw-r--r--MediaBrowser.sln42
-rw-r--r--Nuget/MediaBrowser.Common.nuspec2
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec4
-rw-r--r--SocketHttpListener.Portable/Net/EndPointListener.cs7
-rw-r--r--SocketHttpListener.Portable/Net/EndPointManager.cs2
-rw-r--r--SocketHttpListener.Portable/Net/HttpConnection.cs11
-rw-r--r--SocketHttpListener.Portable/Net/HttpListener.cs13
-rw-r--r--SocketHttpListener.Portable/Net/ResponseStream.cs68
133 files changed, 1910 insertions, 1486 deletions
diff --git a/Emby.Common.Implementations/IO/ManagedFileSystem.cs b/Emby.Common.Implementations/IO/ManagedFileSystem.cs
index 3ed4f650f..7d14e521f 100644
--- a/Emby.Common.Implementations/IO/ManagedFileSystem.cs
+++ b/Emby.Common.Implementations/IO/ManagedFileSystem.cs
@@ -392,10 +392,27 @@ namespace Emby.Common.Implementations.IO
if (_supportsAsyncFileStreams && isAsync)
{
- return new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), 262144, true);
+ return GetFileStream(path, mode, access, share, FileOpenOptions.Asynchronous);
}
- return new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), 262144);
+ return GetFileStream(path, mode, access, share, FileOpenOptions.None);
+ }
+
+ public Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, FileOpenOptions fileOpenOptions)
+ {
+ if (_sharpCifsFileSystem.IsEnabledForPath(path))
+ {
+ return _sharpCifsFileSystem.GetFileStream(path, mode, access, share);
+ }
+
+ var defaultBufferSize = 4096;
+ return new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), defaultBufferSize, GetFileOptions(fileOpenOptions));
+ }
+
+ private FileOptions GetFileOptions(FileOpenOptions mode)
+ {
+ var val = (int)mode;
+ return (FileOptions)val;
}
private FileMode GetFileMode(FileOpenMode mode)
@@ -501,6 +518,49 @@ namespace Emby.Common.Implementations.IO
}
}
+ public void SetAttributes(string path, bool isHidden, bool isReadOnly)
+ {
+ if (_sharpCifsFileSystem.IsEnabledForPath(path))
+ {
+ _sharpCifsFileSystem.SetAttributes(path, isHidden, isReadOnly);
+ return;
+ }
+
+ var info = GetFileInfo(path);
+
+ if (!info.Exists)
+ {
+ return;
+ }
+
+ if (info.IsReadOnly == isReadOnly && info.IsHidden == isHidden)
+ {
+ return;
+ }
+
+ var attributes = File.GetAttributes(path);
+
+ if (isReadOnly)
+ {
+ attributes = attributes | FileAttributes.ReadOnly;
+ }
+ else
+ {
+ attributes = RemoveAttribute(attributes, FileAttributes.ReadOnly);
+ }
+
+ if (isHidden)
+ {
+ attributes = attributes | FileAttributes.Hidden;
+ }
+ else
+ {
+ attributes = RemoveAttribute(attributes, FileAttributes.Hidden);
+ }
+
+ File.SetAttributes(path, attributes);
+ }
+
private static FileAttributes RemoveAttribute(FileAttributes attributes, FileAttributes attributesToRemove)
{
return attributes & ~attributesToRemove;
@@ -673,20 +733,7 @@ namespace Emby.Common.Implementations.IO
return;
}
- var fileInfo = GetFileInfo(path);
-
- if (fileInfo.Exists)
- {
- if (fileInfo.IsHidden)
- {
- SetHidden(path, false);
- }
- if (fileInfo.IsReadOnly)
- {
- SetReadOnly(path, false);
- }
- }
-
+ SetAttributes(path, false, false);
File.Delete(path);
}
diff --git a/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs b/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs
index 0a407d64f..64cac7623 100644
--- a/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs
+++ b/Emby.Common.Implementations/IO/SharpCifsFileSystem.cs
@@ -53,6 +53,11 @@ namespace Emby.Common.Implementations.IO
if (separator == '/')
{
result = result.Replace('\\', '/');
+
+ if (result.StartsWith("smb:/", StringComparison.OrdinalIgnoreCase) && !result.StartsWith("smb://", StringComparison.OrdinalIgnoreCase))
+ {
+ result = result.Replace("smb:/", "smb://");
+ }
}
return result;
@@ -161,23 +166,38 @@ namespace Emby.Common.Implementations.IO
public void SetHidden(string path, bool isHidden)
{
var file = CreateSmbFile(path);
+ SetHidden(file, isHidden);
+ }
+
+ public void SetReadOnly(string path, bool isReadOnly)
+ {
+ var file = CreateSmbFile(path);
+ SetReadOnly(file, isReadOnly);
+ }
+ public void SetAttributes(string path, bool isHidden, bool isReadOnly)
+ {
+ var file = CreateSmbFile(path);
+ SetHidden(file, isHidden);
+ SetReadOnly(file, isReadOnly);
+ }
+
+ private void SetHidden(SmbFile file, bool isHidden)
+ {
var isCurrentlyHidden = file.IsHidden();
if (isCurrentlyHidden && !isHidden)
{
- file.SetAttributes(file.GetAttributes() & ~SmbFile.AttrReadonly);
+ file.SetAttributes(file.GetAttributes() & ~SmbFile.AttrHidden);
}
else if (!isCurrentlyHidden && isHidden)
{
- file.SetAttributes(file.GetAttributes() | SmbFile.AttrReadonly);
+ file.SetAttributes(file.GetAttributes() | SmbFile.AttrHidden);
}
}
- public void SetReadOnly(string path, bool isReadOnly)
+ private void SetReadOnly(SmbFile file, bool isReadOnly)
{
- var file = CreateSmbFile(path);
-
var isCurrentlyReadOnly = !file.CanWrite();
if (isCurrentlyReadOnly && !isReadOnly)
diff --git a/Emby.Common.Implementations/project.json b/Emby.Common.Implementations/project.json
index 674101e8a..ff60c740e 100644
--- a/Emby.Common.Implementations/project.json
+++ b/Emby.Common.Implementations/project.json
@@ -45,7 +45,7 @@
"System.Net.Requests": "4.3.0",
"System.Xml.ReaderWriter": "4.3.0",
"System.Xml.XmlSerializer": "4.3.0",
- "System.Net.Http": "4.3.0",
+ "System.Net.Http": "4.3.2",
"System.Net.Primitives": "4.3.0",
"System.Net.Sockets": "4.3.0",
"System.Net.NetworkInformation": "4.3.0",
diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs
index 8f62e6d27..b09dba70c 100644
--- a/Emby.Dlna/DlnaManager.cs
+++ b/Emby.Dlna/DlnaManager.cs
@@ -587,10 +587,7 @@ namespace Emby.Dlna
new DirectTvProfile(),
new DishHopperJoeyProfile(),
new DefaultProfile(),
- new PopcornHourProfile(),
- new VlcProfile(),
- new BubbleUpnpProfile(),
- new KodiProfile(),
+ new PopcornHourProfile()
};
foreach (var item in list)
diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj
index a8c05a527..cae5a9636 100644
--- a/Emby.Dlna/Emby.Dlna.csproj
+++ b/Emby.Dlna/Emby.Dlna.csproj
@@ -79,13 +79,11 @@
<Compile Include="PlayTo\uParserObject.cs" />
<Compile Include="PlayTo\UpnpContainer.cs" />
<Compile Include="PlayTo\uPnpNamespaces.cs" />
- <Compile Include="Profiles\BubbleUpnpProfile.cs" />
<Compile Include="Profiles\DefaultProfile.cs" />
<Compile Include="Profiles\DenonAvrProfile.cs" />
<Compile Include="Profiles\DirectTvProfile.cs" />
<Compile Include="Profiles\DishHopperJoeyProfile.cs" />
<Compile Include="Profiles\Foobar2000Profile.cs" />
- <Compile Include="Profiles\KodiProfile.cs" />
<Compile Include="Profiles\LgTvProfile.cs" />
<Compile Include="Profiles\LinksysDMA2100Profile.cs" />
<Compile Include="Profiles\MediaMonkeyProfile.cs" />
@@ -105,7 +103,6 @@
<Compile Include="Profiles\SonyBravia2014Profile.cs" />
<Compile Include="Profiles\SonyPs3Profile.cs" />
<Compile Include="Profiles\SonyPs4Profile.cs" />
- <Compile Include="Profiles\VlcProfile.cs" />
<Compile Include="Profiles\WdtvLiveProfile.cs" />
<Compile Include="Profiles\Xbox360Profile.cs" />
<Compile Include="Profiles\XboxOneProfile.cs" />
@@ -153,13 +150,11 @@
<EmbeddedResource Include="Profiles\Xml\Sharp Smart TV.xml" />
</ItemGroup>
<ItemGroup>
- <EmbeddedResource Include="Profiles\Xml\BubbleUPnp.xml" />
<EmbeddedResource Include="Profiles\Xml\Default.xml" />
<EmbeddedResource Include="Profiles\Xml\Denon AVR.xml" />
<EmbeddedResource Include="Profiles\Xml\DirecTV HD-DVR.xml" />
<EmbeddedResource Include="Profiles\Xml\Dish Hopper-Joey.xml" />
<EmbeddedResource Include="Profiles\Xml\foobar2000.xml" />
- <EmbeddedResource Include="Profiles\Xml\Kodi.xml" />
<EmbeddedResource Include="Profiles\Xml\LG Smart TV.xml" />
<EmbeddedResource Include="Profiles\Xml\Linksys DMA2100.xml" />
<EmbeddedResource Include="Profiles\Xml\MediaMonkey.xml" />
@@ -178,7 +173,6 @@
<EmbeddedResource Include="Profiles\Xml\Sony Bravia %282014%29.xml" />
<EmbeddedResource Include="Profiles\Xml\Sony PlayStation 3.xml" />
<EmbeddedResource Include="Profiles\Xml\Sony PlayStation 4.xml" />
- <EmbeddedResource Include="Profiles\Xml\Vlc.xml" />
<EmbeddedResource Include="Profiles\Xml\WDTV Live.xml" />
<EmbeddedResource Include="Profiles\Xml\Xbox 360.xml" />
<EmbeddedResource Include="Profiles\Xml\Xbox One.xml" />
diff --git a/Emby.Dlna/Profiles/BubbleUpnpProfile.cs b/Emby.Dlna/Profiles/BubbleUpnpProfile.cs
deleted file mode 100644
index b551bff2a..000000000
--- a/Emby.Dlna/Profiles/BubbleUpnpProfile.cs
+++ /dev/null
@@ -1,146 +0,0 @@
-using MediaBrowser.Model.Dlna;
-using System.Xml.Serialization;
-
-namespace Emby.Dlna.Profiles
-{
- [XmlRoot("Profile")]
- public class BubbleUpnpProfile : DefaultProfile
- {
- public BubbleUpnpProfile()
- {
- Name = "BubbleUPnp";
-
- Identification = new DeviceIdentification
- {
- ModelName = "BubbleUPnp",
-
- Headers = new[]
- {
- new HttpHeaderInfo {Name = "User-Agent", Value = "BubbleUPnp", Match = HeaderMatchType.Substring}
- }
- };
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- AudioCodec = "mp3",
- Type = DlnaProfileType.Audio
- },
-
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video,
- AudioCodec = "aac",
- VideoCodec = "h264"
- },
-
- new TranscodingProfile
- {
- Container = "jpeg",
- Type = DlnaProfileType.Photo
- }
- };
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Container = "",
- Type = DlnaProfileType.Video
- },
-
- new DirectPlayProfile
- {
- Container = "",
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Container = "",
- Type = DlnaProfileType.Photo,
- }
- };
-
- ResponseProfiles = new ResponseProfile[] { };
-
- ContainerProfiles = new ContainerProfile[] { };
-
- CodecProfiles = new CodecProfile[] { };
-
- SubtitleProfiles = new[]
- {
- new SubtitleProfile
- {
- Format = "srt",
- Method = SubtitleDeliveryMethod.External,
- },
-
- new SubtitleProfile
- {
- Format = "sub",
- Method = SubtitleDeliveryMethod.External,
- },
-
- new SubtitleProfile
- {
- Format = "srt",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "ass",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "ssa",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "smi",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "dvdsub",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "pgs",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "pgssub",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "sub",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- }
- };
- }
- }
-}
diff --git a/Emby.Dlna/Profiles/DefaultProfile.cs b/Emby.Dlna/Profiles/DefaultProfile.cs
index e99b22f2d..1413e89d2 100644
--- a/Emby.Dlna/Profiles/DefaultProfile.cs
+++ b/Emby.Dlna/Profiles/DefaultProfile.cs
@@ -30,8 +30,8 @@ namespace Emby.Dlna.Profiles
MaxIconWidth = 48;
MaxIconHeight = 48;
- MaxStreamingBitrate = 30000000;
- MaxStaticBitrate = 30000000;
+ MaxStreamingBitrate = 40000000;
+ MaxStaticBitrate = 40000000;
MusicStreamingTranscodingBitrate = 192000;
EnableAlbumArtInDidl = false;
@@ -64,15 +64,13 @@ namespace Emby.Dlna.Profiles
{
new DirectPlayProfile
{
- Container = "m4v,ts,mpegts,mkv,avi,mpg,mpeg,mp4,mov",
- VideoCodec = "h264",
- AudioCodec = "aac,mp3,ac3",
+ Container = "m4v,mpegts,ts,3gp,mov,xvid,vob,mkv,wmv,asf,ogm,ogv,m2v,avi,mpg,mpeg,mp4,webm,wtv,m2ts,dvr-ms",
Type = DlnaProfileType.Video
},
new DirectPlayProfile
{
- Container = "mp3,wma,aac,wav,flac",
+ Container = "aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac",
Type = DlnaProfileType.Audio
}
};
@@ -82,13 +80,61 @@ namespace Emby.Dlna.Profiles
new SubtitleProfile
{
Format = "srt",
- Method = SubtitleDeliveryMethod.Embed
+ Method = SubtitleDeliveryMethod.External,
},
new SubtitleProfile
{
- Format = "srt",
+ Format = "sub",
Method = SubtitleDeliveryMethod.External,
+ },
+
+ new SubtitleProfile
+ {
+ Format = "srt",
+ Method = SubtitleDeliveryMethod.Embed
+ },
+
+ new SubtitleProfile
+ {
+ Format = "ass",
+ Method = SubtitleDeliveryMethod.Embed
+ },
+
+ new SubtitleProfile
+ {
+ Format = "ssa",
+ Method = SubtitleDeliveryMethod.Embed
+ },
+
+ new SubtitleProfile
+ {
+ Format = "smi",
+ Method = SubtitleDeliveryMethod.Embed
+ },
+
+ new SubtitleProfile
+ {
+ Format = "dvdsub",
+ Method = SubtitleDeliveryMethod.Embed
+ },
+
+ new SubtitleProfile
+ {
+ Format = "pgs",
+ Method = SubtitleDeliveryMethod.Embed
+ },
+
+ new SubtitleProfile
+ {
+ Format = "pgssub",
+ Method = SubtitleDeliveryMethod.Embed
+ },
+
+ new SubtitleProfile
+ {
+ Format = "sub",
+ Method = SubtitleDeliveryMethod.Embed
}
};
diff --git a/Emby.Dlna/Profiles/KodiProfile.cs b/Emby.Dlna/Profiles/KodiProfile.cs
deleted file mode 100644
index dbcac6652..000000000
--- a/Emby.Dlna/Profiles/KodiProfile.cs
+++ /dev/null
@@ -1,151 +0,0 @@
-using MediaBrowser.Model.Dlna;
-using System.Xml.Serialization;
-
-namespace Emby.Dlna.Profiles
-{
- [XmlRoot("Profile")]
- public class KodiProfile : DefaultProfile
- {
- public KodiProfile()
- {
- Name = "Kodi";
-
- MaxStreamingBitrate = 100000000;
- MusicStreamingTranscodingBitrate = 1280000;
-
- TimelineOffsetSeconds = 5;
-
- Identification = new DeviceIdentification
- {
- ModelName = "Kodi",
-
- Headers = new[]
- {
- new HttpHeaderInfo {Name = "User-Agent", Value = "Kodi", Match = HeaderMatchType.Substring}
- }
- };
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- AudioCodec = "mp3",
- Type = DlnaProfileType.Audio
- },
-
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video,
- AudioCodec = "aac",
- VideoCodec = "h264"
- },
-
- new TranscodingProfile
- {
- Container = "jpeg",
- Type = DlnaProfileType.Photo
- }
- };
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Container = "",
- Type = DlnaProfileType.Video
- },
-
- new DirectPlayProfile
- {
- Container = "",
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Container = "",
- Type = DlnaProfileType.Photo,
- }
- };
-
- ResponseProfiles = new ResponseProfile[] { };
-
- ContainerProfiles = new ContainerProfile[] { };
-
- CodecProfiles = new CodecProfile[] { };
-
- SubtitleProfiles = new[]
- {
- new SubtitleProfile
- {
- Format = "srt",
- Method = SubtitleDeliveryMethod.External,
- },
-
- new SubtitleProfile
- {
- Format = "sub",
- Method = SubtitleDeliveryMethod.External,
- },
-
- new SubtitleProfile
- {
- Format = "srt",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "ass",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "ssa",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "smi",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "dvdsub",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "pgs",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "pgssub",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "sub",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- }
- };
- }
- }
-}
diff --git a/Emby.Dlna/Profiles/VlcProfile.cs b/Emby.Dlna/Profiles/VlcProfile.cs
deleted file mode 100644
index 2cd0e5cae..000000000
--- a/Emby.Dlna/Profiles/VlcProfile.cs
+++ /dev/null
@@ -1,149 +0,0 @@
-using MediaBrowser.Model.Dlna;
-using System.Xml.Serialization;
-
-namespace Emby.Dlna.Profiles
-{
- [XmlRoot("Profile")]
- public class VlcProfile : DefaultProfile
- {
- public VlcProfile()
- {
- Name = "Vlc";
-
-
- TimelineOffsetSeconds = 5;
-
- Identification = new DeviceIdentification
- {
- ModelName = "Vlc",
-
- Headers = new[]
- {
- new HttpHeaderInfo {Name = "User-Agent", Value = "vlc", Match = HeaderMatchType.Substring}
- }
- };
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- AudioCodec = "mp3",
- Type = DlnaProfileType.Audio
- },
-
- new TranscodingProfile
- {
- Container = "ts",
- Type = DlnaProfileType.Video,
- AudioCodec = "aac",
- VideoCodec = "h264"
- },
-
- new TranscodingProfile
- {
- Container = "jpeg",
- Type = DlnaProfileType.Photo
- }
- };
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Container = "",
- Type = DlnaProfileType.Video
- },
-
- new DirectPlayProfile
- {
- Container = "",
- Type = DlnaProfileType.Audio
- },
-
- new DirectPlayProfile
- {
- Container = "",
- Type = DlnaProfileType.Photo,
- }
- };
-
- ResponseProfiles = new ResponseProfile[] { };
-
- ContainerProfiles = new ContainerProfile[] { };
-
- CodecProfiles = new CodecProfile[] { };
-
- SubtitleProfiles = new[]
- {
- new SubtitleProfile
- {
- Format = "srt",
- Method = SubtitleDeliveryMethod.External,
- },
-
- new SubtitleProfile
- {
- Format = "sub",
- Method = SubtitleDeliveryMethod.External,
- },
-
- new SubtitleProfile
- {
- Format = "srt",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "ass",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "ssa",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "smi",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "dvdsub",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "pgs",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "pgssub",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- },
-
- new SubtitleProfile
- {
- Format = "sub",
- Method = SubtitleDeliveryMethod.Embed,
- DidlMode = "",
- }
- };
- }
- }
-}
diff --git a/Emby.Dlna/Profiles/Xml/BubbleUPnp.xml b/Emby.Dlna/Profiles/Xml/BubbleUPnp.xml
deleted file mode 100644
index 84bfa336a..000000000
--- a/Emby.Dlna/Profiles/Xml/BubbleUPnp.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0"?>
-<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <Name>BubbleUPnp</Name>
- <Identification>
- <ModelName>BubbleUPnp</ModelName>
- <Headers>
- <HttpHeaderInfo name="User-Agent" value="BubbleUPnp" match="Substring" />
- </Headers>
- </Identification>
- <Manufacturer>Emby</Manufacturer>
- <ManufacturerUrl>http://emby.media/</ManufacturerUrl>
- <ModelName>Emby Server</ModelName>
- <ModelDescription>Emby</ModelDescription>
- <ModelNumber>Emby</ModelNumber>
- <ModelUrl>http://emby.media/</ModelUrl>
- <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
- <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
- <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
- <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
- <AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
- <MaxIconWidth>48</MaxIconWidth>
- <MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
- <MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
- <MaxStaticMusicBitrate xsi:nil="true" />
- <XDlnaDoc>DMS-1.50</XDlnaDoc>
- <ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
- <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
- <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
- <RequiresPlainFolders>false</RequiresPlainFolders>
- <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
- <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
- <XmlRootAttributes />
- <DirectPlayProfiles>
- <DirectPlayProfile container="" type="Video" />
- <DirectPlayProfile container="" type="Audio" />
- <DirectPlayProfile container="" type="Photo" />
- </DirectPlayProfiles>
- <TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
- </TranscodingProfiles>
- <ContainerProfiles />
- <CodecProfiles />
- <ResponseProfiles />
- <SubtitleProfiles>
- <SubtitleProfile format="srt" method="External" />
- <SubtitleProfile format="sub" method="External" />
- <SubtitleProfile format="srt" method="Embed" didlMode="" />
- <SubtitleProfile format="ass" method="Embed" didlMode="" />
- <SubtitleProfile format="ssa" method="Embed" didlMode="" />
- <SubtitleProfile format="smi" method="Embed" didlMode="" />
- <SubtitleProfile format="dvdsub" method="Embed" didlMode="" />
- <SubtitleProfile format="pgs" method="Embed" didlMode="" />
- <SubtitleProfile format="pgssub" method="Embed" didlMode="" />
- <SubtitleProfile format="sub" method="Embed" didlMode="" />
- </SubtitleProfiles>
-</Profile> \ No newline at end of file
diff --git a/Emby.Dlna/Profiles/Xml/Default.xml b/Emby.Dlna/Profiles/Xml/Default.xml
index 6d39ac1da..9c4e68d96 100644
--- a/Emby.Dlna/Profiles/Xml/Default.xml
+++ b/Emby.Dlna/Profiles/Xml/Default.xml
@@ -16,8 +16,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
@@ -29,8 +29,8 @@
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<XmlRootAttributes />
<DirectPlayProfiles>
- <DirectPlayProfile container="m4v,ts,mpegts,mkv,avi,mpg,mpeg,mp4,mov" audioCodec="aac,mp3,ac3" videoCodec="h264" type="Video" />
- <DirectPlayProfile container="mp3,wma,aac,wav,flac" type="Audio" />
+ <DirectPlayProfile container="m4v,mpegts,ts,3gp,mov,xvid,vob,mkv,wmv,asf,ogm,ogv,m2v,avi,mpg,mpeg,mp4,webm,wtv,m2ts,dvr-ms" type="Video" />
+ <DirectPlayProfile container="aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac" type="Audio" />
</DirectPlayProfiles>
<TranscodingProfiles>
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
@@ -45,7 +45,15 @@
</ResponseProfile>
</ResponseProfiles>
<SubtitleProfiles>
- <SubtitleProfile format="srt" method="Embed" />
<SubtitleProfile format="srt" method="External" />
+ <SubtitleProfile format="sub" method="External" />
+ <SubtitleProfile format="srt" method="Embed" />
+ <SubtitleProfile format="ass" method="Embed" />
+ <SubtitleProfile format="ssa" method="Embed" />
+ <SubtitleProfile format="smi" method="Embed" />
+ <SubtitleProfile format="dvdsub" method="Embed" />
+ <SubtitleProfile format="pgs" method="Embed" />
+ <SubtitleProfile format="pgssub" method="Embed" />
+ <SubtitleProfile format="sub" method="Embed" />
</SubtitleProfiles>
</Profile> \ No newline at end of file
diff --git a/Emby.Dlna/Profiles/Xml/Denon AVR.xml b/Emby.Dlna/Profiles/Xml/Denon AVR.xml
index 9c6af71ed..772e9a41c 100644
--- a/Emby.Dlna/Profiles/Xml/Denon AVR.xml
+++ b/Emby.Dlna/Profiles/Xml/Denon AVR.xml
@@ -21,8 +21,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
@@ -45,7 +45,15 @@
<CodecProfiles />
<ResponseProfiles />
<SubtitleProfiles>
- <SubtitleProfile format="srt" method="Embed" />
<SubtitleProfile format="srt" method="External" />
+ <SubtitleProfile format="sub" method="External" />
+ <SubtitleProfile format="srt" method="Embed" />
+ <SubtitleProfile format="ass" method="Embed" />
+ <SubtitleProfile format="ssa" method="Embed" />
+ <SubtitleProfile format="smi" method="Embed" />
+ <SubtitleProfile format="dvdsub" method="Embed" />
+ <SubtitleProfile format="pgs" method="Embed" />
+ <SubtitleProfile format="pgssub" method="Embed" />
+ <SubtitleProfile format="sub" method="Embed" />
</SubtitleProfiles>
</Profile> \ No newline at end of file
diff --git a/Emby.Dlna/Profiles/Xml/DirecTV HD-DVR.xml b/Emby.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
index bb0fd0bb2..381a9f641 100644
--- a/Emby.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
+++ b/Emby.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
@@ -22,8 +22,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Dish Hopper-Joey.xml b/Emby.Dlna/Profiles/Xml/Dish Hopper-Joey.xml
index fc8496510..4eb67ae81 100644
--- a/Emby.Dlna/Profiles/Xml/Dish Hopper-Joey.xml
+++ b/Emby.Dlna/Profiles/Xml/Dish Hopper-Joey.xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Kodi.xml b/Emby.Dlna/Profiles/Xml/Kodi.xml
deleted file mode 100644
index 286417d96..000000000
--- a/Emby.Dlna/Profiles/Xml/Kodi.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0"?>
-<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <Name>Kodi</Name>
- <Identification>
- <ModelName>Kodi</ModelName>
- <Headers>
- <HttpHeaderInfo name="User-Agent" value="Kodi" match="Substring" />
- </Headers>
- </Identification>
- <Manufacturer>Emby</Manufacturer>
- <ManufacturerUrl>http://emby.media/</ManufacturerUrl>
- <ModelName>Emby Server</ModelName>
- <ModelDescription>Emby</ModelDescription>
- <ModelNumber>Emby</ModelNumber>
- <ModelUrl>http://emby.media/</ModelUrl>
- <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
- <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
- <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
- <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
- <AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
- <MaxIconWidth>48</MaxIconWidth>
- <MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>100000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
- <MusicStreamingTranscodingBitrate>1280000</MusicStreamingTranscodingBitrate>
- <MaxStaticMusicBitrate xsi:nil="true" />
- <XDlnaDoc>DMS-1.50</XDlnaDoc>
- <ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
- <TimelineOffsetSeconds>5</TimelineOffsetSeconds>
- <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
- <RequiresPlainFolders>false</RequiresPlainFolders>
- <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
- <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
- <XmlRootAttributes />
- <DirectPlayProfiles>
- <DirectPlayProfile container="" type="Video" />
- <DirectPlayProfile container="" type="Audio" />
- <DirectPlayProfile container="" type="Photo" />
- </DirectPlayProfiles>
- <TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
- </TranscodingProfiles>
- <ContainerProfiles />
- <CodecProfiles />
- <ResponseProfiles />
- <SubtitleProfiles>
- <SubtitleProfile format="srt" method="External" />
- <SubtitleProfile format="sub" method="External" />
- <SubtitleProfile format="srt" method="Embed" didlMode="" />
- <SubtitleProfile format="ass" method="Embed" didlMode="" />
- <SubtitleProfile format="ssa" method="Embed" didlMode="" />
- <SubtitleProfile format="smi" method="Embed" didlMode="" />
- <SubtitleProfile format="dvdsub" method="Embed" didlMode="" />
- <SubtitleProfile format="pgs" method="Embed" didlMode="" />
- <SubtitleProfile format="pgssub" method="Embed" didlMode="" />
- <SubtitleProfile format="sub" method="Embed" didlMode="" />
- </SubtitleProfiles>
-</Profile> \ No newline at end of file
diff --git a/Emby.Dlna/Profiles/Xml/LG Smart TV.xml b/Emby.Dlna/Profiles/Xml/LG Smart TV.xml
index e48af3842..a61fefcc8 100644
--- a/Emby.Dlna/Profiles/Xml/LG Smart TV.xml
+++ b/Emby.Dlna/Profiles/Xml/LG Smart TV.xml
@@ -22,8 +22,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Linksys DMA2100.xml b/Emby.Dlna/Profiles/Xml/Linksys DMA2100.xml
index 7f1518154..bd20112a8 100644
--- a/Emby.Dlna/Profiles/Xml/Linksys DMA2100.xml
+++ b/Emby.Dlna/Profiles/Xml/Linksys DMA2100.xml
@@ -20,8 +20,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/MediaMonkey.xml b/Emby.Dlna/Profiles/Xml/MediaMonkey.xml
index 3d5b39896..325c2e836 100644
--- a/Emby.Dlna/Profiles/Xml/MediaMonkey.xml
+++ b/Emby.Dlna/Profiles/Xml/MediaMonkey.xml
@@ -22,8 +22,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
@@ -51,7 +51,15 @@
<CodecProfiles />
<ResponseProfiles />
<SubtitleProfiles>
- <SubtitleProfile format="srt" method="Embed" />
<SubtitleProfile format="srt" method="External" />
+ <SubtitleProfile format="sub" method="External" />
+ <SubtitleProfile format="srt" method="Embed" />
+ <SubtitleProfile format="ass" method="Embed" />
+ <SubtitleProfile format="ssa" method="Embed" />
+ <SubtitleProfile format="smi" method="Embed" />
+ <SubtitleProfile format="dvdsub" method="Embed" />
+ <SubtitleProfile format="pgs" method="Embed" />
+ <SubtitleProfile format="pgssub" method="Embed" />
+ <SubtitleProfile format="sub" method="Embed" />
</SubtitleProfiles>
</Profile> \ No newline at end of file
diff --git a/Emby.Dlna/Profiles/Xml/Panasonic Viera.xml b/Emby.Dlna/Profiles/Xml/Panasonic Viera.xml
index 689f2813c..1c58ab0c9 100644
--- a/Emby.Dlna/Profiles/Xml/Panasonic Viera.xml
+++ b/Emby.Dlna/Profiles/Xml/Panasonic Viera.xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Popcorn Hour.xml b/Emby.Dlna/Profiles/Xml/Popcorn Hour.xml
index 4da6fa3fa..69bf74a98 100644
--- a/Emby.Dlna/Profiles/Xml/Popcorn Hour.xml
+++ b/Emby.Dlna/Profiles/Xml/Popcorn Hour.xml
@@ -16,8 +16,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Samsung Smart TV.xml b/Emby.Dlna/Profiles/Xml/Samsung Smart TV.xml
index fbdc7bc4f..6fbed0590 100644
--- a/Emby.Dlna/Profiles/Xml/Samsung Smart TV.xml
+++ b/Emby.Dlna/Profiles/Xml/Samsung Smart TV.xml
@@ -22,8 +22,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sharp Smart TV.xml b/Emby.Dlna/Profiles/Xml/Sharp Smart TV.xml
index 2ca6ff605..ae2e686b8 100644
--- a/Emby.Dlna/Profiles/Xml/Sharp Smart TV.xml
+++ b/Emby.Dlna/Profiles/Xml/Sharp Smart TV.xml
@@ -22,8 +22,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml b/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
index d3735a9ed..576f5ca50 100644
--- a/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
+++ b/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
@@ -26,8 +26,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2014.xml b/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2014.xml
index c5c62cb73..5a04afb3e 100644
--- a/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2014.xml
+++ b/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2014.xml
@@ -26,8 +26,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2015.xml b/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2015.xml
index fd0ff91a0..97f0e3790 100644
--- a/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2015.xml
+++ b/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2015.xml
@@ -24,8 +24,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2016.xml b/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2016.xml
index 66c942bfe..052bc80d8 100644
--- a/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2016.xml
+++ b/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player 2016.xml
@@ -24,8 +24,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player.xml b/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
index 7113a4583..084fa9df0 100644
--- a/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
+++ b/Emby.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
@@ -24,8 +24,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony Bravia (2010).xml b/Emby.Dlna/Profiles/Xml/Sony Bravia (2010).xml
index e5fe83f0f..046282ba3 100644
--- a/Emby.Dlna/Profiles/Xml/Sony Bravia (2010).xml
+++ b/Emby.Dlna/Profiles/Xml/Sony Bravia (2010).xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony Bravia (2011).xml b/Emby.Dlna/Profiles/Xml/Sony Bravia (2011).xml
index 8bbaefed9..e30afa2af 100644
--- a/Emby.Dlna/Profiles/Xml/Sony Bravia (2011).xml
+++ b/Emby.Dlna/Profiles/Xml/Sony Bravia (2011).xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony Bravia (2012).xml b/Emby.Dlna/Profiles/Xml/Sony Bravia (2012).xml
index 4e51116a0..cff07f04c 100644
--- a/Emby.Dlna/Profiles/Xml/Sony Bravia (2012).xml
+++ b/Emby.Dlna/Profiles/Xml/Sony Bravia (2012).xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony Bravia (2013).xml b/Emby.Dlna/Profiles/Xml/Sony Bravia (2013).xml
index 002b31a27..2d5794087 100644
--- a/Emby.Dlna/Profiles/Xml/Sony Bravia (2013).xml
+++ b/Emby.Dlna/Profiles/Xml/Sony Bravia (2013).xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony Bravia (2014).xml b/Emby.Dlna/Profiles/Xml/Sony Bravia (2014).xml
index 2067a1d45..d61b986c2 100644
--- a/Emby.Dlna/Profiles/Xml/Sony Bravia (2014).xml
+++ b/Emby.Dlna/Profiles/Xml/Sony Bravia (2014).xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony PlayStation 3.xml b/Emby.Dlna/Profiles/Xml/Sony PlayStation 3.xml
index bea72c410..966ecc2c8 100644
--- a/Emby.Dlna/Profiles/Xml/Sony PlayStation 3.xml
+++ b/Emby.Dlna/Profiles/Xml/Sony PlayStation 3.xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Sony PlayStation 4.xml b/Emby.Dlna/Profiles/Xml/Sony PlayStation 4.xml
index 128e0cf1f..6a818193b 100644
--- a/Emby.Dlna/Profiles/Xml/Sony PlayStation 4.xml
+++ b/Emby.Dlna/Profiles/Xml/Sony PlayStation 4.xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Vlc.xml b/Emby.Dlna/Profiles/Xml/Vlc.xml
deleted file mode 100644
index cd35f3f91..000000000
--- a/Emby.Dlna/Profiles/Xml/Vlc.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0"?>
-<Profile xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <Name>Vlc</Name>
- <Identification>
- <ModelName>Vlc</ModelName>
- <Headers>
- <HttpHeaderInfo name="User-Agent" value="vlc" match="Substring" />
- </Headers>
- </Identification>
- <Manufacturer>Emby</Manufacturer>
- <ManufacturerUrl>http://emby.media/</ManufacturerUrl>
- <ModelName>Emby Server</ModelName>
- <ModelDescription>Emby</ModelDescription>
- <ModelNumber>Emby</ModelNumber>
- <ModelUrl>http://emby.media/</ModelUrl>
- <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
- <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit>
- <EnableSingleSubtitleLimit>false</EnableSingleSubtitleLimit>
- <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
- <AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
- <MaxIconWidth>48</MaxIconWidth>
- <MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
- <MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
- <MaxStaticMusicBitrate xsi:nil="true" />
- <XDlnaDoc>DMS-1.50</XDlnaDoc>
- <ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
- <TimelineOffsetSeconds>5</TimelineOffsetSeconds>
- <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
- <RequiresPlainFolders>false</RequiresPlainFolders>
- <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar>
- <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
- <XmlRootAttributes />
- <DirectPlayProfiles>
- <DirectPlayProfile container="" type="Video" />
- <DirectPlayProfile container="" type="Audio" />
- <DirectPlayProfile container="" type="Photo" />
- </DirectPlayProfiles>
- <TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" enableSubtitlesInManifest="false" minSegments="0" segmentLength="0" breakOnNonKeyFrames="false" />
- </TranscodingProfiles>
- <ContainerProfiles />
- <CodecProfiles />
- <ResponseProfiles />
- <SubtitleProfiles>
- <SubtitleProfile format="srt" method="External" />
- <SubtitleProfile format="sub" method="External" />
- <SubtitleProfile format="srt" method="Embed" didlMode="" />
- <SubtitleProfile format="ass" method="Embed" didlMode="" />
- <SubtitleProfile format="ssa" method="Embed" didlMode="" />
- <SubtitleProfile format="smi" method="Embed" didlMode="" />
- <SubtitleProfile format="dvdsub" method="Embed" didlMode="" />
- <SubtitleProfile format="pgs" method="Embed" didlMode="" />
- <SubtitleProfile format="pgssub" method="Embed" didlMode="" />
- <SubtitleProfile format="sub" method="Embed" didlMode="" />
- </SubtitleProfiles>
-</Profile> \ No newline at end of file
diff --git a/Emby.Dlna/Profiles/Xml/WDTV Live.xml b/Emby.Dlna/Profiles/Xml/WDTV Live.xml
index acb972703..71b346318 100644
--- a/Emby.Dlna/Profiles/Xml/WDTV Live.xml
+++ b/Emby.Dlna/Profiles/Xml/WDTV Live.xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Xbox 360.xml b/Emby.Dlna/Profiles/Xml/Xbox 360.xml
index e46c52f4c..3b7d2963f 100644
--- a/Emby.Dlna/Profiles/Xml/Xbox 360.xml
+++ b/Emby.Dlna/Profiles/Xml/Xbox 360.xml
@@ -24,8 +24,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/Xbox One.xml b/Emby.Dlna/Profiles/Xml/Xbox One.xml
index cffc386b1..423327a38 100644
--- a/Emby.Dlna/Profiles/Xml/Xbox One.xml
+++ b/Emby.Dlna/Profiles/Xml/Xbox One.xml
@@ -23,8 +23,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
diff --git a/Emby.Dlna/Profiles/Xml/foobar2000.xml b/Emby.Dlna/Profiles/Xml/foobar2000.xml
index 192ba5a30..febc12a8f 100644
--- a/Emby.Dlna/Profiles/Xml/foobar2000.xml
+++ b/Emby.Dlna/Profiles/Xml/foobar2000.xml
@@ -22,8 +22,8 @@
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
<MaxIconWidth>48</MaxIconWidth>
<MaxIconHeight>48</MaxIconHeight>
- <MaxStreamingBitrate>30000000</MaxStreamingBitrate>
- <MaxStaticBitrate>30000000</MaxStaticBitrate>
+ <MaxStreamingBitrate>40000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>40000000</MaxStaticBitrate>
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
<MaxStaticMusicBitrate xsi:nil="true" />
<XDlnaDoc>DMS-1.50</XDlnaDoc>
@@ -51,7 +51,15 @@
<CodecProfiles />
<ResponseProfiles />
<SubtitleProfiles>
- <SubtitleProfile format="srt" method="Embed" />
<SubtitleProfile format="srt" method="External" />
+ <SubtitleProfile format="sub" method="External" />
+ <SubtitleProfile format="srt" method="Embed" />
+ <SubtitleProfile format="ass" method="Embed" />
+ <SubtitleProfile format="ssa" method="Embed" />
+ <SubtitleProfile format="smi" method="Embed" />
+ <SubtitleProfile format="dvdsub" method="Embed" />
+ <SubtitleProfile format="pgs" method="Embed" />
+ <SubtitleProfile format="pgssub" method="Embed" />
+ <SubtitleProfile format="sub" method="Embed" />
</SubtitleProfiles>
</Profile> \ No newline at end of file
diff --git a/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs
index 500f57aad..f603c4950 100644
--- a/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs
+++ b/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs
@@ -105,17 +105,6 @@ namespace Emby.Drawing.ImageMagick
}
}
- public void CropWhiteSpace(string inputPath, string outputPath)
- {
- CheckDisposed();
-
- using (var wand = new MagickWand(inputPath))
- {
- wand.CurrentImage.TrimImage(10);
- wand.SaveImage(outputPath);
- }
- }
-
public ImageSize GetImageSize(string path)
{
CheckDisposed();
@@ -150,6 +139,11 @@ namespace Emby.Drawing.ImageMagick
{
using (var originalImage = new MagickWand(inputPath))
{
+ if (options.CropWhiteSpace)
+ {
+ originalImage.CurrentImage.TrimImage(10);
+ }
+
ScaleImage(originalImage, width, height, options.Blur ?? 0);
if (autoOrient)
diff --git a/Emby.Drawing.Net/GDIImageEncoder.cs b/Emby.Drawing.Net/GDIImageEncoder.cs
index 638415afd..e710baaa7 100644
--- a/Emby.Drawing.Net/GDIImageEncoder.cs
+++ b/Emby.Drawing.Net/GDIImageEncoder.cs
@@ -75,27 +75,24 @@ namespace Emby.Drawing.Net
}
}
- public void CropWhiteSpace(string inputPath, string outputPath)
+ private Image GetImage(string path, bool cropWhitespace)
{
- using (var image = (Bitmap)Image.FromFile(inputPath))
+ if (cropWhitespace)
{
- using (var croppedImage = image.CropWhitespace())
+ using (var originalImage = (Bitmap)Image.FromFile(path))
{
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath));
-
- using (var outputStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
- {
- croppedImage.Save(System.Drawing.Imaging.ImageFormat.Png, outputStream, 100);
- }
+ return originalImage.CropWhitespace();
}
}
+
+ return Image.FromFile(path);
}
public void EncodeImage(string inputPath, string cacheFilePath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
{
var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0;
- using (var originalImage = Image.FromFile(inputPath))
+ using (var originalImage = GetImage(inputPath, options.CropWhiteSpace))
{
var newWidth = Convert.ToInt32(width);
var newHeight = Convert.ToInt32(height);
diff --git a/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj b/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj
new file mode 100644
index 000000000..d7b33b950
--- /dev/null
+++ b/Emby.Drawing.Skia/Emby.Drawing.Skia.csproj
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{2312DA6D-FF86-4597-9777-BCEEC32D96DD}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Emby.Drawing.Skia</RootNamespace>
+ <AssemblyName>Emby.Drawing.Skia</AssemblyName>
+ <DefaultLanguage>en-US</DefaultLanguage>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <!-- A reference to the entire .NET Framework is automatically included -->
+ <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
+ <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project>
+ <Name>MediaBrowser.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj">
+ <Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
+ <Name>MediaBrowser.Controller</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
+ <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
+ <Name>MediaBrowser.Model</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\SharedVersion.cs">
+ <Link>Properties\SharedVersion.cs</Link>
+ </Compile>
+ <Compile Include="PercentPlayedDrawer.cs" />
+ <Compile Include="PlayedIndicatorDrawer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SkiaEncoder.cs" />
+ <Compile Include="StripCollageBuilder.cs" />
+ <Compile Include="UnplayedCountIndicator.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="SkiaSharp, Version=1.57.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+ <HintPath>..\packages\SkiaSharp.1.57.1\lib\portable-net45+win8+wpa81+wp8\SkiaSharp.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="fonts\robotoregular.ttf" />
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Emby.Drawing.Skia/PercentPlayedDrawer.cs b/Emby.Drawing.Skia/PercentPlayedDrawer.cs
new file mode 100644
index 000000000..e291a462b
--- /dev/null
+++ b/Emby.Drawing.Skia/PercentPlayedDrawer.cs
@@ -0,0 +1,31 @@
+using SkiaSharp;
+using MediaBrowser.Model.Drawing;
+using System;
+
+namespace Emby.Drawing.Skia
+{
+ public class PercentPlayedDrawer
+ {
+ private const int IndicatorHeight = 8;
+
+ public void Process(SKCanvas canvas, ImageSize imageSize, double percent)
+ {
+ using (var paint = new SKPaint())
+ {
+ var endX = imageSize.Width - 1;
+ var endY = imageSize.Height - 1;
+
+ paint.Color = SKColor.Parse("#99000000");
+ paint.Style = SKPaintStyle.Fill;
+ canvas.DrawRect(SKRect.Create(0, (float)endY - IndicatorHeight, (float)endX, (float)endY), paint);
+
+ double foregroundWidth = endX;
+ foregroundWidth *= percent;
+ foregroundWidth /= 100;
+
+ paint.Color = SKColor.Parse("#FF52B54B");
+ canvas.DrawRect(SKRect.Create(0, (float)endY - IndicatorHeight, Convert.ToInt32(Math.Round(foregroundWidth)), (float)endY), paint);
+ }
+ }
+ }
+}
diff --git a/Emby.Drawing.Skia/PlayedIndicatorDrawer.cs b/Emby.Drawing.Skia/PlayedIndicatorDrawer.cs
new file mode 100644
index 000000000..9f3a74eb7
--- /dev/null
+++ b/Emby.Drawing.Skia/PlayedIndicatorDrawer.cs
@@ -0,0 +1,120 @@
+using SkiaSharp;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Drawing;
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+using System.Reflection;
+
+namespace Emby.Drawing.Skia
+{
+ public class PlayedIndicatorDrawer
+ {
+ private const int FontSize = 42;
+ private const int OffsetFromTopRightCorner = 38;
+
+ private readonly IApplicationPaths _appPaths;
+ private readonly IHttpClient _iHttpClient;
+ private readonly IFileSystem _fileSystem;
+
+ public PlayedIndicatorDrawer(IApplicationPaths appPaths, IHttpClient iHttpClient, IFileSystem fileSystem)
+ {
+ _appPaths = appPaths;
+ _iHttpClient = iHttpClient;
+ _fileSystem = fileSystem;
+ }
+
+ public async Task DrawPlayedIndicator(SKCanvas canvas, ImageSize imageSize)
+ {
+ var x = imageSize.Width - OffsetFromTopRightCorner;
+
+ using (var paint = new SKPaint())
+ {
+ paint.Color = SKColor.Parse("#CC52B54B");
+ paint.Style = SKPaintStyle.Fill;
+ canvas.DrawCircle((float)x, OffsetFromTopRightCorner, 20, paint);
+ }
+
+ using (var paint = new SKPaint())
+ {
+ paint.Color = new SKColor(255, 255, 255, 255);
+ paint.Style = SKPaintStyle.Fill;
+ paint.Typeface = SKTypeface.FromFile(await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf",
+ _appPaths, _iHttpClient, _fileSystem).ConfigureAwait(false));
+ paint.TextSize = FontSize;
+ paint.IsAntialias = true;
+
+ canvas.DrawText("a", (float)x-20, OffsetFromTopRightCorner + 12, paint);
+ }
+ }
+
+ internal static string ExtractFont(string name, IApplicationPaths paths, IFileSystem fileSystem)
+ {
+ var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name);
+
+ if (fileSystem.FileExists(filePath))
+ {
+ return filePath;
+ }
+
+ var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name;
+ var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf");
+ fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath));
+
+ using (var stream = typeof(PlayedIndicatorDrawer).GetTypeInfo().Assembly.GetManifestResourceStream(namespacePath))
+ {
+ using (var fileStream = fileSystem.GetFileStream(tempPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
+ {
+ stream.CopyTo(fileStream);
+ }
+ }
+
+ fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
+
+ try
+ {
+ fileSystem.CopyFile(tempPath, filePath, false);
+ }
+ catch (IOException)
+ {
+
+ }
+
+ return tempPath;
+ }
+
+ 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 (fileSystem.FileExists(filePath))
+ {
+ return filePath;
+ }
+
+ var tempPath = await httpClient.GetTempFile(new HttpRequestOptions
+ {
+ Url = url,
+ Progress = new Progress<double>()
+
+ }).ConfigureAwait(false);
+
+ fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
+
+ try
+ {
+ fileSystem.CopyFile(tempPath, filePath, false);
+ }
+ catch (IOException)
+ {
+
+ }
+
+ return tempPath;
+ }
+ }
+}
diff --git a/Emby.Drawing.Skia/Properties/AssemblyInfo.cs b/Emby.Drawing.Skia/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..c0dc7c5b4
--- /dev/null
+++ b/Emby.Drawing.Skia/Properties/AssemblyInfo.cs
@@ -0,0 +1,25 @@
+using System.Resources;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Emby.Drawing.Skia")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Emby.Drawing.Skia")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: NeutralResourcesLanguage("en")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+// \ No newline at end of file
diff --git a/Emby.Drawing.Skia/SkiaEncoder.cs b/Emby.Drawing.Skia/SkiaEncoder.cs
new file mode 100644
index 000000000..74ceb7591
--- /dev/null
+++ b/Emby.Drawing.Skia/SkiaEncoder.cs
@@ -0,0 +1,387 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
+using SkiaSharp;
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+
+namespace Emby.Drawing.Skia
+{
+ public class SkiaEncoder : IImageEncoder
+ {
+ private readonly ILogger _logger;
+ private readonly IApplicationPaths _appPaths;
+ private readonly Func<IHttpClient> _httpClientFactory;
+ private readonly IFileSystem _fileSystem;
+
+ public SkiaEncoder(ILogger logger, IApplicationPaths appPaths, Func<IHttpClient> httpClientFactory, IFileSystem fileSystem)
+ {
+ _logger = logger;
+ _appPaths = appPaths;
+ _httpClientFactory = httpClientFactory;
+ _fileSystem = fileSystem;
+
+ LogVersion();
+ }
+
+ public string[] SupportedInputFormats
+ {
+ get
+ {
+ // Some common file name extensions for RAW picture files include: .cr2, .crw, .dng, .nef, .orf, .rw2, .pef, .arw, .sr2, .srf, and .tif.
+ return new[]
+ {
+ "jpeg",
+ "jpg",
+ "png",
+ "dng",
+ "webp",
+ "gif",
+ "bmp",
+ "ico",
+ "astc",
+ "ktx",
+ "pkm",
+ "wbmp"
+ };
+ }
+ }
+
+ public ImageFormat[] SupportedOutputFormats
+ {
+ get
+ {
+ return new[] { ImageFormat.Webp, ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png, ImageFormat.Bmp };
+ }
+ }
+
+ private void LogVersion()
+ {
+ _logger.Info("SkiaSharp version: " + GetVersion());
+ }
+
+ public static string GetVersion()
+ {
+ using (var bitmap = new SKBitmap())
+ {
+ return typeof(SKBitmap).GetTypeInfo().Assembly.GetName().Version.ToString();
+ }
+ }
+
+ private static bool IsWhiteSpace(SKColor color)
+ {
+ return (color.Red == 255 && color.Green == 255 && color.Blue == 255) || color.Alpha == 0;
+ }
+
+ public static SKEncodedImageFormat GetImageFormat(ImageFormat selectedFormat)
+ {
+ switch (selectedFormat)
+ {
+ case ImageFormat.Bmp:
+ return SKEncodedImageFormat.Bmp;
+ case ImageFormat.Jpg:
+ return SKEncodedImageFormat.Jpeg;
+ case ImageFormat.Gif:
+ return SKEncodedImageFormat.Gif;
+ case ImageFormat.Webp:
+ return SKEncodedImageFormat.Webp;
+ default:
+ return SKEncodedImageFormat.Png;
+ }
+ }
+
+ private static bool IsAllWhiteRow(SKBitmap bmp, int row)
+ {
+ for (var i = 0; i < bmp.Width; ++i)
+ {
+ if (!IsWhiteSpace(bmp.GetPixel(i, row)))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static bool IsAllWhiteColumn(SKBitmap bmp, int col)
+ {
+ for (var i = 0; i < bmp.Height; ++i)
+ {
+ if (!IsWhiteSpace(bmp.GetPixel(col, i)))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private SKBitmap CropWhiteSpace(SKBitmap bitmap)
+ {
+ var topmost = 0;
+ for (int row = 0; row < bitmap.Height; ++row)
+ {
+ if (IsAllWhiteRow(bitmap, row))
+ topmost = row;
+ else break;
+ }
+
+ int bottommost = 0;
+ for (int row = bitmap.Height - 1; row >= 0; --row)
+ {
+ if (IsAllWhiteRow(bitmap, row))
+ bottommost = row;
+ else break;
+ }
+
+ int leftmost = 0, rightmost = 0;
+ for (int col = 0; col < bitmap.Width; ++col)
+ {
+ if (IsAllWhiteColumn(bitmap, col))
+ leftmost = col;
+ else
+ break;
+ }
+
+ for (int col = bitmap.Width - 1; col >= 0; --col)
+ {
+ if (IsAllWhiteColumn(bitmap, col))
+ rightmost = col;
+ else
+ break;
+ }
+
+ var newRect = SKRectI.Create(leftmost, topmost, rightmost - leftmost, bottommost - topmost);
+
+ using (var image = SKImage.FromBitmap(bitmap))
+ {
+ using (var subset = image.Subset(newRect))
+ {
+ return SKBitmap.FromImage(subset);
+ //using (var data = subset.Encode(StripCollageBuilder.GetEncodedFormat(outputPath), 90))
+ //{
+ // using (var fileStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
+ // {
+ // data.AsStream().CopyTo(fileStream);
+ // }
+ //}
+ }
+ }
+ }
+
+ public ImageSize GetImageSize(string path)
+ {
+ using (var s = new SKFileStream(path))
+ {
+ using (var codec = SKCodec.Create(s))
+ {
+ var info = codec.Info;
+
+ return new ImageSize
+ {
+ Width = info.Width,
+ Height = info.Height
+ };
+ }
+ }
+ }
+
+ private string[] TransparentImageTypes = new string[] { ".png", ".gif", ".webp" };
+ private SKBitmap Decode(string path)
+ {
+ var requiresTransparencyHack = TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty);
+
+ if (requiresTransparencyHack)
+ {
+ using (var stream = new SKFileStream(path))
+ {
+ var codec = SKCodec.Create(stream);
+
+ // create the bitmap
+ var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height);
+ // decode
+ codec.GetPixels(bitmap.Info, bitmap.GetPixels());
+
+ return bitmap;
+ }
+ }
+
+ return SKBitmap.Decode(path);
+ }
+
+ private SKBitmap GetBitmap(string path, bool cropWhitespace)
+ {
+ if (cropWhitespace)
+ {
+ using (var bitmap = Decode(path))
+ {
+ return CropWhiteSpace(bitmap);
+ }
+ }
+
+ return Decode(path);
+ }
+
+ public void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
+ {
+ if (string.IsNullOrWhiteSpace(inputPath))
+ {
+ throw new ArgumentNullException("inputPath");
+ }
+ if (string.IsNullOrWhiteSpace(inputPath))
+ {
+ throw new ArgumentNullException("outputPath");
+ }
+
+ var skiaOutputFormat = GetImageFormat(selectedOutputFormat);
+
+ var hasBackgroundColor = !string.IsNullOrWhiteSpace(options.BackgroundColor);
+ var hasForegroundColor = !string.IsNullOrWhiteSpace(options.ForegroundLayer);
+ var blur = options.Blur ?? 0;
+ var hasIndicator = options.AddPlayedIndicator || options.UnplayedCount.HasValue || !options.PercentPlayed.Equals(0);
+
+ using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace))
+ {
+ using (var resizedBitmap = new SKBitmap(width, height))//, bitmap.ColorType, bitmap.AlphaType))
+ {
+ // scale image
+ var resizeMethod = SKBitmapResizeMethod.Lanczos3;
+
+ bitmap.Resize(resizedBitmap, resizeMethod);
+
+ // If all we're doing is resizing then we can stop now
+ if (!hasBackgroundColor && !hasForegroundColor && blur == 0 && !hasIndicator)
+ {
+ using (var outputStream = new SKFileWStream(outputPath))
+ {
+ resizedBitmap.Encode(outputStream, skiaOutputFormat, quality);
+ return;
+ }
+ }
+
+ // create bitmap to use for canvas drawing
+ using (var saveBitmap = new SKBitmap(width, height))//, bitmap.ColorType, bitmap.AlphaType))
+ {
+ // create canvas used to draw into bitmap
+ using (var canvas = new SKCanvas(saveBitmap))
+ {
+ // set background color if present
+ if (hasBackgroundColor)
+ {
+ canvas.Clear(SKColor.Parse(options.BackgroundColor));
+ }
+
+ // Add blur if option is present
+ if (blur > 0)
+ {
+ using (var paint = new SKPaint())
+ {
+ // create image from resized bitmap to apply blur
+ using (var filter = SKImageFilter.CreateBlur(blur, blur))
+ {
+ paint.ImageFilter = filter;
+ canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height), paint);
+ }
+ }
+ }
+ else
+ {
+ // draw resized bitmap onto canvas
+ canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height));
+ }
+
+ // If foreground layer present then draw
+ if (hasForegroundColor)
+ {
+ Double opacity;
+ if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4;
+
+ canvas.DrawColor(new SKColor(0, 0, 0, (Byte)((1 - opacity) * 0xFF)), SKBlendMode.SrcOver);
+ }
+
+ if (hasIndicator)
+ {
+ DrawIndicator(canvas, width, height, options);
+ }
+
+ using (var outputStream = new SKFileWStream(outputPath))
+ {
+ saveBitmap.Encode(outputStream, skiaOutputFormat, quality);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void CreateImageCollage(ImageCollageOptions options)
+ {
+ double ratio = options.Width;
+ ratio /= options.Height;
+
+ if (ratio >= 1.4)
+ {
+ new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
+ }
+ else if (ratio >= .9)
+ {
+ new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
+ }
+ else
+ {
+ // @todo create Poster collage capability
+ new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
+ }
+ }
+
+ private void DrawIndicator(SKCanvas canvas, int imageWidth, int imageHeight, ImageProcessingOptions options)
+ {
+ try
+ {
+ var currentImageSize = new ImageSize(imageWidth, imageHeight);
+
+ if (options.AddPlayedIndicator)
+ {
+ var task = new PlayedIndicatorDrawer(_appPaths, _httpClientFactory(), _fileSystem).DrawPlayedIndicator(canvas, currentImageSize);
+ Task.WaitAll(task);
+ }
+ else if (options.UnplayedCount.HasValue)
+ {
+ new UnplayedCountIndicator(_appPaths, _httpClientFactory(), _fileSystem).DrawUnplayedCountIndicator(canvas, currentImageSize, options.UnplayedCount.Value);
+ }
+
+ if (options.PercentPlayed > 0)
+ {
+ new PercentPlayedDrawer().Process(canvas, currentImageSize, options.PercentPlayed);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error drawing indicator overlay", ex);
+ }
+ }
+
+ public string Name
+ {
+ get { return "Skia"; }
+ }
+
+ public void Dispose()
+ {
+ }
+
+ public bool SupportsImageCollageCreation
+ {
+ get { return true; }
+ }
+
+ public bool SupportsImageEncoding
+ {
+ get { return true; }
+ }
+ }
+} \ No newline at end of file
diff --git a/Emby.Drawing.Skia/StripCollageBuilder.cs b/Emby.Drawing.Skia/StripCollageBuilder.cs
new file mode 100644
index 000000000..605677aab
--- /dev/null
+++ b/Emby.Drawing.Skia/StripCollageBuilder.cs
@@ -0,0 +1,190 @@
+using SkiaSharp;
+using MediaBrowser.Common.Configuration;
+using System;
+using System.IO;
+using MediaBrowser.Model.IO;
+
+namespace Emby.Drawing.Skia
+{
+ public class StripCollageBuilder
+ {
+ private readonly IApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
+
+ public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem)
+ {
+ _appPaths = appPaths;
+ _fileSystem = fileSystem;
+ }
+
+ public static SKEncodedImageFormat GetEncodedFormat(string outputPath)
+ {
+ var ext = Path.GetExtension(outputPath).ToLower();
+
+ if (ext == ".jpg" || ext == ".jpeg")
+ return SKEncodedImageFormat.Jpeg;
+
+ if (ext == ".webp")
+ return SKEncodedImageFormat.Webp;
+
+ if (ext == ".gif")
+ return SKEncodedImageFormat.Gif;
+
+ if (ext == ".bmp")
+ return SKEncodedImageFormat.Bmp;
+
+ // default to png
+ return SKEncodedImageFormat.Png;
+ }
+
+ public void BuildPosterCollage(string[] paths, string outputPath, int width, int height)
+ {
+ // @todo
+ }
+
+ public void BuildSquareCollage(string[] paths, string outputPath, int width, int height)
+ {
+ using (var bitmap = BuildSquareCollageBitmap(paths, width, height))
+ {
+ using (var outputStream = new SKFileWStream(outputPath))
+ {
+ bitmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
+ }
+ }
+ }
+
+ public void BuildThumbCollage(string[] paths, string outputPath, int width, int height)
+ {
+ using (var bitmap = BuildThumbCollageBitmap(paths, width, height))
+ {
+ using (var outputStream = new SKFileWStream(outputPath))
+ {
+ bitmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
+ }
+ }
+ }
+
+ private SKBitmap BuildThumbCollageBitmap(string[] paths, int width, int height)
+ {
+ var bitmap = new SKBitmap(width, height);
+
+ using (var canvas = new SKCanvas(bitmap))
+ {
+ canvas.Clear(SKColors.Black);
+
+ // determine sizes for each image that will composited into the final image
+ var iSlice = Convert.ToInt32(width * 0.23475);
+ int iTrans = Convert.ToInt32(height * .25);
+ int iHeight = Convert.ToInt32(height * .70);
+ var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
+ var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
+ int imageIndex = 0;
+
+ for (int i = 0; i < 4; i++)
+ {
+ using (var currentBitmap = SKBitmap.Decode(paths[imageIndex]))
+ {
+ // resize to the same aspect as the original
+ int iWidth = (int)Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height);
+ using (var resizeBitmap = new SKBitmap(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType))
+ {
+ currentBitmap.Resize(resizeBitmap, SKBitmapResizeMethod.Lanczos3);
+ // determine how much to crop
+ int ix = (int)Math.Abs((iWidth - iSlice) / 2);
+ using (var image = SKImage.FromBitmap(resizeBitmap))
+ {
+ // crop image
+ using (var subset = image.Subset(SKRectI.Create(ix, 0, iSlice, iHeight)))
+ {
+ // draw image onto canvas
+ canvas.DrawImage(subset, (horizontalImagePadding * (i + 1)) + (iSlice * i), verticalSpacing);
+
+ using (var croppedBitmap = SKBitmap.FromImage(subset))
+ {
+ // create reflection of image below the drawn image
+ using (var reflectionBitmap = new SKBitmap(croppedBitmap.Width, croppedBitmap.Height / 2, croppedBitmap.ColorType, croppedBitmap.AlphaType))
+ {
+ // resize to half height
+ croppedBitmap.Resize(reflectionBitmap, SKBitmapResizeMethod.Lanczos3);
+
+ using (var flippedBitmap = new SKBitmap(reflectionBitmap.Width, reflectionBitmap.Height, reflectionBitmap.ColorType, reflectionBitmap.AlphaType))
+ {
+ using (var flippedCanvas = new SKCanvas(flippedBitmap))
+ {
+ // flip image vertically
+ var matrix = SKMatrix.MakeScale(1, -1);
+ matrix.SetScaleTranslate(1, -1, 0, flippedBitmap.Height);
+ flippedCanvas.SetMatrix(matrix);
+ flippedCanvas.DrawBitmap(reflectionBitmap, 0, 0);
+ flippedCanvas.ResetMatrix();
+
+ // create gradient to make image appear as a reflection
+ var remainingHeight = height - (iHeight + (2 * verticalSpacing));
+ flippedCanvas.ClipRect(SKRect.Create(reflectionBitmap.Width, remainingHeight));
+ using (var gradient = new SKPaint())
+ {
+ gradient.IsAntialias = true;
+ gradient.BlendMode = SKBlendMode.SrcOver;
+ gradient.Shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(0, remainingHeight), new[] { new SKColor(0, 0, 0, 128), new SKColor(0, 0, 0, 208), new SKColor(0, 0, 0, 240), new SKColor(0, 0, 0, 255) }, null, SKShaderTileMode.Clamp);
+ flippedCanvas.DrawPaint(gradient);
+ }
+
+ // finally draw reflection onto canvas
+ canvas.DrawBitmap(flippedBitmap, (horizontalImagePadding * (i + 1)) + (iSlice * i), iHeight + (2 * verticalSpacing));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ imageIndex++;
+
+ if (imageIndex >= paths.Length)
+ imageIndex = 0;
+ }
+ }
+
+ return bitmap;
+ }
+
+ private SKBitmap BuildSquareCollageBitmap(string[] paths, int width, int height)
+ {
+ var bitmap = new SKBitmap(width, height);
+ var imageIndex = 0;
+ var cellWidth = width / 2;
+ var cellHeight = height / 2;
+
+ using (var canvas = new SKCanvas(bitmap))
+ {
+ for (var x = 0; x < 2; x++)
+ {
+ for (var y = 0; y < 2; y++)
+ {
+ using (var currentBitmap = SKBitmap.Decode(paths[imageIndex]))
+ {
+ using (var resizedBitmap = new SKBitmap(cellWidth, cellHeight, currentBitmap.ColorType, currentBitmap.AlphaType))
+ {
+ // scale image
+ currentBitmap.Resize(resizedBitmap, SKBitmapResizeMethod.Lanczos3);
+
+ // draw this image into the strip at the next position
+ var xPos = x * cellWidth;
+ var yPos = y * cellHeight;
+ canvas.DrawBitmap(resizedBitmap, xPos, yPos);
+ }
+ }
+ imageIndex++;
+
+ if (imageIndex >= paths.Length)
+ imageIndex = 0;
+ }
+ }
+ }
+
+ return bitmap;
+ }
+ }
+} \ No newline at end of file
diff --git a/Emby.Drawing.Skia/UnplayedCountIndicator.cs b/Emby.Drawing.Skia/UnplayedCountIndicator.cs
new file mode 100644
index 000000000..f0283ad23
--- /dev/null
+++ b/Emby.Drawing.Skia/UnplayedCountIndicator.cs
@@ -0,0 +1,68 @@
+using SkiaSharp;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Drawing;
+using System.Globalization;
+using System.Threading.Tasks;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.IO;
+
+namespace Emby.Drawing.Skia
+{
+ public class UnplayedCountIndicator
+ {
+ private const int OffsetFromTopRightCorner = 38;
+
+ private readonly IApplicationPaths _appPaths;
+ private readonly IHttpClient _iHttpClient;
+ private readonly IFileSystem _fileSystem;
+
+ public UnplayedCountIndicator(IApplicationPaths appPaths, IHttpClient iHttpClient, IFileSystem fileSystem)
+ {
+ _appPaths = appPaths;
+ _iHttpClient = iHttpClient;
+ _fileSystem = fileSystem;
+ }
+
+ public void DrawUnplayedCountIndicator(SKCanvas canvas, ImageSize imageSize, int count)
+ {
+ var x = imageSize.Width - OffsetFromTopRightCorner;
+ var text = count.ToString(CultureInfo.InvariantCulture);
+
+ using (var paint = new SKPaint())
+ {
+ paint.Color = SKColor.Parse("#CC52B54B");
+ paint.Style = SKPaintStyle.Fill;
+ canvas.DrawCircle((float)x, OffsetFromTopRightCorner, 20, paint);
+ }
+ using (var paint = new SKPaint())
+ {
+ paint.Color = new SKColor(255, 255, 255, 255);
+ paint.Style = SKPaintStyle.Fill;
+ paint.Typeface = SKTypeface.FromFile(PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths, _fileSystem));
+ paint.TextSize = 24;
+ paint.IsAntialias = true;
+
+ var y = OffsetFromTopRightCorner + 9;
+
+ if (text.Length == 1)
+ {
+ x -= 7;
+ }
+ if (text.Length == 2)
+ {
+ x -= 13;
+ }
+ else if (text.Length >= 3)
+ {
+ x -= 15;
+ y -= 2;
+ paint.TextSize = 18;
+ }
+
+ canvas.DrawText(text, (float)x, y, paint);
+ }
+ }
+ }
+}
diff --git a/Emby.Drawing.Skia/packages.config b/Emby.Drawing.Skia/packages.config
new file mode 100644
index 000000000..0743c3809
--- /dev/null
+++ b/Emby.Drawing.Skia/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="SkiaSharp" version="1.57.1" targetFramework="portable45-net45+win8" />
+</packages> \ No newline at end of file
diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs
index bee0e9b69..82181238b 100644
--- a/Emby.Drawing/ImageProcessor.cs
+++ b/Emby.Drawing/ImageProcessor.cs
@@ -56,7 +56,7 @@ namespace Emby.Drawing
private readonly IFileSystem _fileSystem;
private readonly IJsonSerializer _jsonSerializer;
private readonly IServerApplicationPaths _appPaths;
- private readonly IImageEncoder _imageEncoder;
+ private IImageEncoder _imageEncoder;
private readonly Func<ILibraryManager> _libraryManager;
public ImageProcessor(ILogger logger,
@@ -64,7 +64,7 @@ namespace Emby.Drawing
IFileSystem fileSystem,
IJsonSerializer jsonSerializer,
IImageEncoder imageEncoder,
- int maxConcurrentImageProcesses, Func<ILibraryManager> libraryManager, ITimerFactory timerFactory)
+ Func<ILibraryManager> libraryManager, ITimerFactory timerFactory)
{
_logger = logger;
_fileSystem = fileSystem;
@@ -103,6 +103,20 @@ namespace Emby.Drawing
_cachedImagedSizes = new ConcurrentDictionary<Guid, ImageSize>(sizeDictionary);
}
+ public IImageEncoder ImageEncoder
+ {
+ get { return _imageEncoder; }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ _imageEncoder = value;
+ }
+ }
+
public string[] SupportedInputFormats
{
get
@@ -136,14 +150,6 @@ namespace Emby.Drawing
}
}
- private string CroppedWhitespaceImageCachePath
- {
- get
- {
- return Path.Combine(_appPaths.ImageCachePath, "cropped-images");
- }
- }
-
public void AddParts(IEnumerable<IImageEnhancer> enhancers)
{
ImageEnhancers = enhancers.ToArray();
@@ -186,14 +192,6 @@ namespace Emby.Drawing
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
- if (options.CropWhiteSpace && _imageEncoder.SupportsImageEncoding)
- {
- var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified).ConfigureAwait(false);
-
- originalImagePath = tuple.Item1;
- dateModified = tuple.Item2;
- }
-
if (options.Enhancers.Count > 0)
{
var tuple = await GetEnhancedImage(new ItemImageInfo
@@ -214,7 +212,7 @@ namespace Emby.Drawing
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
- ImageSize? originalImageSize;
+ ImageSize? originalImageSize = null;
try
{
originalImageSize = GetImageSize(originalImagePath, dateModified, true);
@@ -241,8 +239,8 @@ namespace Emby.Drawing
if (!_fileSystem.FileExists(cacheFilePath))
{
- var newWidth = Convert.ToInt32(newSize.Width);
- var newHeight = Convert.ToInt32(newSize.Height);
+ var newWidth = Convert.ToInt32(Math.Round(newSize.Width));
+ var newHeight = Convert.ToInt32(Math.Round(newSize.Height));
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
@@ -349,22 +347,22 @@ namespace Emby.Drawing
return new ImageSize(options.Width.Value, options.Height.Value);
}
- var aspect = GetEstimatedAspectRatio(options.Image.Type);
+ var aspect = GetEstimatedAspectRatio(options.Image.Type, options.Item);
var width = options.Width ?? options.MaxWidth;
if (width.HasValue)
{
- var heightValue = aspect / width.Value;
- return new ImageSize(width.Value, Convert.ToInt32(heightValue));
+ var heightValue = width.Value / aspect;
+ return new ImageSize(width.Value, heightValue);
}
var height = options.Height ?? options.MaxHeight ?? 200;
var widthValue = aspect * height;
- return new ImageSize(Convert.ToInt32(widthValue), height);
+ return new ImageSize(widthValue, height);
}
- private double GetEstimatedAspectRatio(ImageType type)
+ private double GetEstimatedAspectRatio(ImageType type, IHasImages item)
{
switch (type)
{
@@ -384,7 +382,7 @@ namespace Emby.Drawing
case ImageType.Logo:
return 2.58;
case ImageType.Primary:
- return .667;
+ return item.GetDefaultPrimaryImageAspectRatio() ?? .667;
default:
return 1;
}
@@ -400,46 +398,6 @@ namespace Emby.Drawing
return requestedFormat;
}
- /// <summary>
- /// Crops whitespace from an image, caches the result, and returns the cached path
- /// </summary>
- private async Task<Tuple<string, DateTime>> GetWhitespaceCroppedImage(string originalImagePath, DateTime dateModified)
- {
- var name = originalImagePath;
- name += "datemodified=" + dateModified.Ticks;
-
- var croppedImagePath = GetCachePath(CroppedWhitespaceImageCachePath, name, Path.GetExtension(originalImagePath));
-
- // Check again in case of contention
- if (_fileSystem.FileExists(croppedImagePath))
- {
- return GetResult(croppedImagePath);
- }
-
- try
- {
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(croppedImagePath));
- var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(croppedImagePath));
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
-
- _imageEncoder.CropWhiteSpace(originalImagePath, tmpPath);
- CopyFile(tmpPath, croppedImagePath);
- return GetResult(tmpPath);
- }
- catch (NotImplementedException)
- {
- // No need to spam the log with an error message
- return new Tuple<string, DateTime>(originalImagePath, dateModified);
- }
- catch (Exception ex)
- {
- // We have to have a catch-all here because some of the .net image methods throw a plain old Exception
- _logger.ErrorException("Error cropping image {0}", ex, originalImagePath);
-
- return new Tuple<string, DateTime>(originalImagePath, dateModified);
- }
- }
-
private Tuple<string, DateTime> GetResult(string path)
{
return new Tuple<string, DateTime>(path, _fileSystem.GetLastWriteTimeUtc(path));
@@ -555,26 +513,39 @@ namespace Emby.Drawing
/// <returns>ImageSize.</returns>
private ImageSize GetImageSizeInternal(string path, bool allowSlowMethod)
{
+ // Can't use taglib because it keeps a lock on the file
+ //try
+ //{
+ // using (var file = TagLib.File.Create(new StreamFileAbstraction(Path.GetFileName(path), _fileSystem.OpenRead(path), null)))
+ // {
+ // var image = file as TagLib.Image.File;
+
+ // var properties = image.Properties;
+
+ // return new ImageSize
+ // {
+ // Height = properties.PhotoHeight,
+ // Width = properties.PhotoWidth
+ // };
+ // }
+ //}
+ //catch
+ //{
+ //}
+
try
{
- using (var file = TagLib.File.Create(new StreamFileAbstraction(Path.GetFileName(path), _fileSystem.OpenRead(path), null)))
- {
- var image = file as TagLib.Image.File;
-
- var properties = image.Properties;
-
- return new ImageSize
- {
- Height = properties.PhotoHeight,
- Width = properties.PhotoWidth
- };
- }
+ return ImageHeader.GetDimensions(path, _logger, _fileSystem);
}
catch
{
- }
+ if (allowSlowMethod)
+ {
+ return _imageEncoder.GetImageSize(path);
+ }
- return ImageHeader.GetDimensions(path, _logger, _fileSystem);
+ throw;
+ }
}
private readonly ITimer _saveImageSizeTimer;
diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs
index 4fa18ce55..c7d365fb2 100644
--- a/Emby.Drawing/NullImageEncoder.cs
+++ b/Emby.Drawing/NullImageEncoder.cs
@@ -57,6 +57,11 @@ namespace Emby.Drawing
get { return false; }
}
+ public ImageSize GetImageSize(string path)
+ {
+ throw new NotImplementedException();
+ }
+
public void Dispose()
{
}
diff --git a/Emby.Server.Core/ApplicationHost.cs b/Emby.Server.Core/ApplicationHost.cs
index 78bdc1189..0fe30eb80 100644
--- a/Emby.Server.Core/ApplicationHost.cs
+++ b/Emby.Server.Core/ApplicationHost.cs
@@ -187,7 +187,7 @@ namespace Emby.Server.Core
/// <value>The HTTP server.</value>
private IHttpServer HttpServer { get; set; }
private IDtoService DtoService { get; set; }
- private IImageProcessor ImageProcessor { get; set; }
+ public IImageProcessor ImageProcessor { get; set; }
/// <summary>
/// Gets or sets the media encoder.
@@ -761,7 +761,10 @@ namespace Emby.Server.Core
return null;
}
- X509Certificate2 localCert = new X509Certificate2(certificateLocation, info.Password);
+ // Don't use an empty string password
+ var password = string.IsNullOrWhiteSpace(info.Password) ? null : info.Password;
+
+ X509Certificate2 localCert = new X509Certificate2(certificateLocation, password);
//localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA;
if (!localCert.HasPrivateKey)
{
@@ -780,14 +783,7 @@ namespace Emby.Server.Core
private IImageProcessor GetImageProcessor()
{
- var maxConcurrentImageProcesses = Math.Max(Environment.ProcessorCount, 4);
-
- if (StartupOptions.ContainsOption("-imagethreads"))
- {
- int.TryParse(StartupOptions.GetOption("-imagethreads"), NumberStyles.Any, CultureInfo.InvariantCulture, out maxConcurrentImageProcesses);
- }
-
- return new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, ImageEncoder, maxConcurrentImageProcesses, () => LibraryManager, TimerFactory);
+ return new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, ImageEncoder, () => LibraryManager, TimerFactory);
}
protected virtual FFMpegInstallInfo GetFfmpegInstallInfo()
@@ -1132,7 +1128,8 @@ namespace Emby.Server.Core
// Custom cert
return new CertificateInfo
{
- Path = ServerConfigurationManager.Configuration.CertificatePath
+ Path = ServerConfigurationManager.Configuration.CertificatePath,
+ Password = ServerConfigurationManager.Configuration.CertificatePassword
};
}
diff --git a/Emby.Server.Core/IO/LibraryMonitor.cs b/Emby.Server.Core/IO/LibraryMonitor.cs
index 8af826c88..0f0640a38 100644
--- a/Emby.Server.Core/IO/LibraryMonitor.cs
+++ b/Emby.Server.Core/IO/LibraryMonitor.cs
@@ -537,7 +537,7 @@ namespace Emby.Server.Core.IO
}
}
- var newRefresher = new FileRefresher(path, _fileSystem, ConfigurationManager, LibraryManager, TaskManager, Logger, _timerFactory, _environmentInfo);
+ var newRefresher = new FileRefresher(path, _fileSystem, ConfigurationManager, LibraryManager, TaskManager, Logger, _timerFactory, _environmentInfo, LibraryManager);
newRefresher.Completed += NewRefresher_Completed;
_activeRefreshers.Add(newRefresher);
}
diff --git a/Emby.Server.Core/project.json b/Emby.Server.Core/project.json
index 70543d7df..fd4f9d6cf 100644
--- a/Emby.Server.Core/project.json
+++ b/Emby.Server.Core/project.json
@@ -68,7 +68,7 @@
"System.AppDomain": "2.0.11",
"System.Globalization.Extensions": "4.3.0",
"System.IO.FileSystem.Watcher": "4.3.0",
- "System.Net.Security": "4.3.0",
+ "System.Net.Security": "4.3.1",
"System.Security.Cryptography.X509Certificates": "4.3.0",
"System.Runtime.Extensions": "4.3.0",
"MediaBrowser.Model": {
diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs
index bf8835846..e9b6f7a40 100644
--- a/Emby.Server.Implementations/Activity/ActivityRepository.cs
+++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs
@@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.Activity
{
using (var statement = db.PrepareStatement("replace into ActivityLogEntries (Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (@Id, @Name, @Overview, @ShortOverview, @Type, @ItemId, @UserId, @DateCreated, @LogSeverity)"))
{
- statement.TryBind("@Id", entry.Id.ToGuidParamValue());
+ statement.TryBind("@Id", entry.Id.ToGuidBlob());
statement.TryBind("@Name", entry.Name);
statement.TryBind("@Overview", entry.Overview);
@@ -168,7 +168,7 @@ namespace Emby.Server.Implementations.Activity
var info = new ActivityLogEntry
{
- Id = reader[index].ReadGuid().ToString("N")
+ Id = reader[index].ReadGuidFromBlob().ToString("N")
};
index++;
diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
index 13874223c..385b4bd51 100644
--- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
+++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
@@ -126,7 +126,7 @@ namespace Emby.Server.Implementations.AppBase
Logger.Info("Saving system configuration");
var path = CommonApplicationPaths.SystemConfigurationFilePath;
- FileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path));
lock (_configurationSyncLock)
{
@@ -293,7 +293,7 @@ namespace Emby.Server.Implementations.AppBase
_configurations.AddOrUpdate(key, configuration, (k, v) => configuration);
var path = GetConfigurationFile(key);
- FileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ FileSystem.CreateDirectory(FileSystem.GetDirectoryName(path));
lock (_configurationSyncLock)
{
diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs
index ad2f45945..d6a41dd67 100644
--- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs
+++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs
@@ -47,7 +47,7 @@ namespace Emby.Server.Implementations.AppBase
// If the file didn't exist before, or if something has changed, re-save
if (buffer == null || !buffer.SequenceEqual(newBytes))
{
- fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ fileSystem.CreateDirectory(fileSystem.GetDirectoryName(path));
// Save it after load in case we got new items
fileSystem.WriteAllBytes(path, newBytes);
diff --git a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs
index f3d84315e..4118bd1b2 100644
--- a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs
@@ -106,8 +106,8 @@ namespace Emby.Server.Implementations.Data
using (var statement = connection.PrepareStatement("replace into userdisplaypreferences (id, userid, client, data) values (@id, @userId, @client, @data)"))
{
- statement.TryBind("@id", displayPreferences.Id.ToGuidParamValue());
- statement.TryBind("@userId", userId.ToGuidParamValue());
+ statement.TryBind("@id", displayPreferences.Id.ToGuidBlob());
+ statement.TryBind("@userId", userId.ToGuidBlob());
statement.TryBind("@client", client);
statement.TryBind("@data", serialized);
@@ -170,8 +170,8 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = connection.PrepareStatement("select data from userdisplaypreferences where id = @id and userId=@userId and client=@client"))
{
- statement.TryBind("@id", guidId.ToGuidParamValue());
- statement.TryBind("@userId", userId.ToGuidParamValue());
+ statement.TryBind("@id", guidId.ToGuidBlob());
+ statement.TryBind("@userId", userId.ToGuidBlob());
statement.TryBind("@client", client);
foreach (var row in statement.ExecuteQuery())
@@ -204,7 +204,7 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = connection.PrepareStatement("select data from userdisplaypreferences where userId=@userId"))
{
- statement.TryBind("@userId", userId.ToGuidParamValue());
+ statement.TryBind("@userId", userId.ToGuidBlob());
foreach (var row in statement.ExecuteQuery())
{
diff --git a/Emby.Server.Implementations/Data/SqliteExtensions.cs b/Emby.Server.Implementations/Data/SqliteExtensions.cs
index 783258a13..d2c851b3c 100644
--- a/Emby.Server.Implementations/Data/SqliteExtensions.cs
+++ b/Emby.Server.Implementations/Data/SqliteExtensions.cs
@@ -26,17 +26,17 @@ namespace Emby.Server.Implementations.Data
});
}
- public static byte[] ToGuidParamValue(this string str)
+ public static byte[] ToGuidBlob(this string str)
{
- return ToGuidParamValue(new Guid(str));
+ return ToGuidBlob(new Guid(str));
}
- public static byte[] ToGuidParamValue(this Guid guid)
+ public static byte[] ToGuidBlob(this Guid guid)
{
return guid.ToByteArray();
}
- public static Guid ReadGuid(this IResultSetValue result)
+ public static Guid ReadGuidFromBlob(this IResultSetValue result)
{
return new Guid(result.ToBlob());
}
@@ -172,7 +172,7 @@ namespace Emby.Server.Implementations.Data
public static Guid GetGuid(this IReadOnlyList<IResultSetValue> result, int index)
{
- return result[index].ReadGuid();
+ return result[index].ReadGuidFromBlob();
}
private static void CheckName(string name)
@@ -262,7 +262,7 @@ namespace Emby.Server.Implementations.Data
IBindParameter bindParam;
if (statement.BindParameters.TryGetValue(name, out bindParam))
{
- bindParam.Bind(value.ToGuidParamValue());
+ bindParam.Bind(value.ToGuidBlob());
}
else
{
diff --git a/Emby.Server.Implementations/Data/SqliteFileOrganizationRepository.cs b/Emby.Server.Implementations/Data/SqliteFileOrganizationRepository.cs
index 9fbe8669d..a254962c9 100644
--- a/Emby.Server.Implementations/Data/SqliteFileOrganizationRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteFileOrganizationRepository.cs
@@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.Data
using (var statement = db.PrepareStatement(commandText))
{
- statement.TryBind("@ResultId", result.Id.ToGuidParamValue());
+ statement.TryBind("@ResultId", result.Id.ToGuidBlob());
statement.TryBind("@OriginalPath", result.OriginalPath);
statement.TryBind("@TargetPath", result.TargetPath);
@@ -100,7 +100,7 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = db.PrepareStatement("delete from FileOrganizerResults where ResultId = @ResultId"))
{
- statement.TryBind("@ResultId", id.ToGuidParamValue());
+ statement.TryBind("@ResultId", id.ToGuidBlob());
statement.MoveNext();
}
}, TransactionMode);
@@ -188,7 +188,7 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = connection.PrepareStatement("select ResultId, OriginalPath, TargetPath, FileLength, OrganizationDate, Status, OrganizationType, StatusMessage, ExtractedName, ExtractedYear, ExtractedSeasonNumber, ExtractedEpisodeNumber, ExtractedEndingEpisodeNumber, DuplicatePaths from FileOrganizerResults where ResultId=@ResultId"))
{
- statement.TryBind("@ResultId", id.ToGuidParamValue());
+ statement.TryBind("@ResultId", id.ToGuidBlob());
foreach (var row in statement.ExecuteQuery())
{
@@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.Data
var result = new FileOrganizationResult
{
- Id = reader[0].ReadGuid().ToString("N")
+ Id = reader[0].ReadGuidFromBlob().ToString("N")
};
index++;
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index 61dce9bba..28be49dc2 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -2128,7 +2128,7 @@ namespace Emby.Server.Implementations.Data
connection.RunInTransaction(db =>
{
// First delete chapters
- db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", id.ToGuidParamValue());
+ db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", id.ToGuidBlob());
using (var saveChapterStatement = PrepareStatement(db, "replace into " + ChaptersTableName + " (ItemId, ChapterIndex, StartPositionTicks, Name, ImagePath, ImageDateModified) values (@ItemId, @ChapterIndex, @StartPositionTicks, @Name, @ImagePath, @ImageDateModified)"))
{
@@ -2139,7 +2139,7 @@ namespace Emby.Server.Implementations.Data
saveChapterStatement.Reset();
}
- saveChapterStatement.TryBind("@ItemId", id.ToGuidParamValue());
+ saveChapterStatement.TryBind("@ItemId", id.ToGuidBlob());
saveChapterStatement.TryBind("@ChapterIndex", index);
saveChapterStatement.TryBind("@StartPositionTicks", chapter.StartPositionTicks);
saveChapterStatement.TryBind("@Name", chapter.Name);
@@ -2919,7 +2919,7 @@ namespace Emby.Server.Implementations.Data
foreach (var row in statement.ExecuteQuery())
{
- list.Add(row[0].ReadGuid());
+ list.Add(row[0].ReadGuidFromBlob());
}
}
@@ -3113,7 +3113,7 @@ namespace Emby.Server.Implementations.Data
foreach (var row in statement.ExecuteQuery())
{
- list.Add(row[0].ReadGuid());
+ list.Add(row[0].ReadGuidFromBlob());
}
}
}
@@ -3643,7 +3643,7 @@ namespace Emby.Server.Implementations.Data
clauses.Add("(select Name from TypedBaseItems where guid=" + paramName + ") in (select Name from People where ItemId=Guid)");
if (statement != null)
{
- statement.TryBind(paramName, personId.ToGuidParamValue());
+ statement.TryBind(paramName, personId.ToGuidBlob());
}
index++;
}
@@ -3843,7 +3843,7 @@ namespace Emby.Server.Implementations.Data
clauses.Add("(select CleanName from TypedBaseItems where guid=" + paramName + ") in (select CleanValue from itemvalues where ItemId=Guid and Type<=1)");
if (statement != null)
{
- statement.TryBind(paramName, artistId.ToGuidParamValue());
+ statement.TryBind(paramName, artistId.ToGuidBlob());
}
index++;
}
@@ -3862,7 +3862,7 @@ namespace Emby.Server.Implementations.Data
clauses.Add("Album in (select Name from typedbaseitems where guid=" + paramName + ")");
if (statement != null)
{
- statement.TryBind(paramName, albumId.ToGuidParamValue());
+ statement.TryBind(paramName, albumId.ToGuidBlob());
}
index++;
}
@@ -3881,7 +3881,7 @@ namespace Emby.Server.Implementations.Data
clauses.Add("(select CleanName from TypedBaseItems where guid=" + paramName + ") not in (select CleanValue from itemvalues where ItemId=Guid and Type<=1)");
if (statement != null)
{
- statement.TryBind(paramName, artistId.ToGuidParamValue());
+ statement.TryBind(paramName, artistId.ToGuidBlob());
}
index++;
}
@@ -3900,7 +3900,7 @@ namespace Emby.Server.Implementations.Data
clauses.Add("(select CleanName from TypedBaseItems where guid=" + paramName + ") in (select CleanValue from itemvalues where ItemId=Guid and Type=2)");
if (statement != null)
{
- statement.TryBind(paramName, genreId.ToGuidParamValue());
+ statement.TryBind(paramName, genreId.ToGuidBlob());
}
index++;
}
@@ -3953,7 +3953,7 @@ namespace Emby.Server.Implementations.Data
clauses.Add("(select CleanName from TypedBaseItems where guid=" + paramName + ") in (select CleanValue from itemvalues where ItemId=Guid and Type=3)");
if (statement != null)
{
- statement.TryBind(paramName, studioId.ToGuidParamValue());
+ statement.TryBind(paramName, studioId.ToGuidBlob());
}
index++;
}
@@ -4521,22 +4521,22 @@ namespace Emby.Server.Implementations.Data
connection.RunInTransaction(db =>
{
// Delete people
- ExecuteWithSingleParam(db, "delete from People where ItemId=@Id", id.ToGuidParamValue());
+ ExecuteWithSingleParam(db, "delete from People where ItemId=@Id", id.ToGuidBlob());
// Delete chapters
- ExecuteWithSingleParam(db, "delete from " + ChaptersTableName + " where ItemId=@Id", id.ToGuidParamValue());
+ ExecuteWithSingleParam(db, "delete from " + ChaptersTableName + " where ItemId=@Id", id.ToGuidBlob());
// Delete media streams
- ExecuteWithSingleParam(db, "delete from mediastreams where ItemId=@Id", id.ToGuidParamValue());
+ ExecuteWithSingleParam(db, "delete from mediastreams where ItemId=@Id", id.ToGuidBlob());
// Delete ancestors
- ExecuteWithSingleParam(db, "delete from AncestorIds where ItemId=@Id", id.ToGuidParamValue());
+ ExecuteWithSingleParam(db, "delete from AncestorIds where ItemId=@Id", id.ToGuidBlob());
// Delete item values
- ExecuteWithSingleParam(db, "delete from ItemValues where ItemId=@Id", id.ToGuidParamValue());
+ ExecuteWithSingleParam(db, "delete from ItemValues where ItemId=@Id", id.ToGuidBlob());
// Delete the item
- ExecuteWithSingleParam(db, "delete from TypedBaseItems where guid=@Id", id.ToGuidParamValue());
+ ExecuteWithSingleParam(db, "delete from TypedBaseItems where guid=@Id", id.ToGuidBlob());
}, TransactionMode);
}
}
@@ -4643,7 +4643,7 @@ namespace Emby.Server.Implementations.Data
whereClauses.Add("ItemId=@ItemId");
if (statement != null)
{
- statement.TryBind("@ItemId", query.ItemId.ToGuidParamValue());
+ statement.TryBind("@ItemId", query.ItemId.ToGuidBlob());
}
}
if (query.AppearsInItemId != Guid.Empty)
@@ -4651,7 +4651,7 @@ namespace Emby.Server.Implementations.Data
whereClauses.Add("Name in (Select Name from People where ItemId=@AppearsInItemId)");
if (statement != null)
{
- statement.TryBind("@AppearsInItemId", query.AppearsInItemId.ToGuidParamValue());
+ statement.TryBind("@AppearsInItemId", query.AppearsInItemId.ToGuidBlob());
}
}
var queryPersonTypes = query.PersonTypes.Where(IsValidPersonType).ToList();
@@ -4730,14 +4730,14 @@ namespace Emby.Server.Implementations.Data
// First delete
deleteAncestorsStatement.Reset();
- deleteAncestorsStatement.TryBind("@ItemId", itemId.ToGuidParamValue());
+ deleteAncestorsStatement.TryBind("@ItemId", itemId.ToGuidBlob());
deleteAncestorsStatement.MoveNext();
foreach (var ancestorId in ancestorIds)
{
updateAncestorsStatement.Reset();
- updateAncestorsStatement.TryBind("@ItemId", itemId.ToGuidParamValue());
- updateAncestorsStatement.TryBind("@AncestorId", ancestorId.ToGuidParamValue());
+ updateAncestorsStatement.TryBind("@ItemId", itemId.ToGuidBlob());
+ updateAncestorsStatement.TryBind("@AncestorId", ancestorId.ToGuidBlob());
updateAncestorsStatement.TryBind("@AncestorIdText", ancestorId.ToString("N"));
updateAncestorsStatement.MoveNext();
}
@@ -5198,7 +5198,7 @@ namespace Emby.Server.Implementations.Data
CheckDisposed();
// First delete
- db.Execute("delete from ItemValues where ItemId=@Id", itemId.ToGuidParamValue());
+ db.Execute("delete from ItemValues where ItemId=@Id", itemId.ToGuidBlob());
using (var statement = PrepareStatement(db, "insert into ItemValues (ItemId, Type, Value, CleanValue) values (@ItemId, @Type, @Value, @CleanValue)"))
{
@@ -5214,7 +5214,7 @@ namespace Emby.Server.Implementations.Data
statement.Reset();
- statement.TryBind("@ItemId", itemId.ToGuidParamValue());
+ statement.TryBind("@ItemId", itemId.ToGuidBlob());
statement.TryBind("@Type", pair.Item1);
statement.TryBind("@Value", itemValue);
@@ -5252,7 +5252,7 @@ namespace Emby.Server.Implementations.Data
{
// First delete
// "delete from People where ItemId=?"
- connection.Execute("delete from People where ItemId=?", itemId.ToGuidParamValue());
+ connection.Execute("delete from People where ItemId=?", itemId.ToGuidBlob());
var listIndex = 0;
@@ -5266,7 +5266,7 @@ namespace Emby.Server.Implementations.Data
statement.Reset();
}
- statement.TryBind("@ItemId", itemId.ToGuidParamValue());
+ statement.TryBind("@ItemId", itemId.ToGuidBlob());
statement.TryBind("@Name", person.Name);
statement.TryBind("@Role", person.Role);
statement.TryBind("@PersonType", person.Type);
@@ -5339,7 +5339,7 @@ namespace Emby.Server.Implementations.Data
using (var statement = PrepareStatementSafe(connection, cmdText))
{
- statement.TryBind("@ItemId", query.ItemId.ToGuidParamValue());
+ statement.TryBind("@ItemId", query.ItemId.ToGuidBlob());
if (query.Type.HasValue)
{
@@ -5383,7 +5383,7 @@ namespace Emby.Server.Implementations.Data
using (var connection = CreateConnection())
{
// First delete chapters
- connection.Execute("delete from mediastreams where ItemId=@ItemId", id.ToGuidParamValue());
+ connection.Execute("delete from mediastreams where ItemId=@ItemId", id.ToGuidBlob());
using (var statement = PrepareStatement(connection, string.Format("replace into mediastreams ({0}) values ({1})",
string.Join(",", _mediaStreamSaveColumns),
@@ -5393,7 +5393,7 @@ namespace Emby.Server.Implementations.Data
{
var paramList = new List<object>();
- paramList.Add(id.ToGuidParamValue());
+ paramList.Add(id.ToGuidBlob());
paramList.Add(stream.Index);
paramList.Add(stream.Type.ToString());
paramList.Add(stream.Codec);
diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
index a31f0ed53..bf6388f5d 100644
--- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
@@ -213,7 +213,7 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = db.PrepareStatement("replace into userdata (key, userId, rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex) values (@key, @userId, @rating,@played,@playCount,@isFavorite,@playbackPositionTicks,@lastPlayedDate,@AudioStreamIndex,@SubtitleStreamIndex)"))
{
- statement.TryBind("@userId", userId.ToGuidParamValue());
+ statement.TryBind("@userId", userId.ToGuidBlob());
statement.TryBind("@key", key);
if (userData.Rating.HasValue)
@@ -311,7 +311,7 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = connection.PrepareStatement("select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where key =@Key and userId=@UserId"))
{
- statement.TryBind("@UserId", userId.ToGuidParamValue());
+ statement.TryBind("@UserId", userId.ToGuidBlob());
statement.TryBind("@Key", key);
foreach (var row in statement.ExecuteQuery())
@@ -364,7 +364,7 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = connection.PrepareStatement("select key,userid,rating,played,playCount,isFavorite,playbackPositionTicks,lastPlayedDate,AudioStreamIndex,SubtitleStreamIndex from userdata where userId=@UserId"))
{
- statement.TryBind("@UserId", userId.ToGuidParamValue());
+ statement.TryBind("@UserId", userId.ToGuidBlob());
foreach (var row in statement.ExecuteQuery())
{
@@ -386,7 +386,7 @@ namespace Emby.Server.Implementations.Data
var userData = new UserItemData();
userData.Key = reader[0].ToString();
- userData.UserId = reader[1].ReadGuid();
+ userData.UserId = reader[1].ReadGuidFromBlob();
if (reader[2].SQLiteType != SQLiteType.Null)
{
diff --git a/Emby.Server.Implementations/Data/SqliteUserRepository.cs b/Emby.Server.Implementations/Data/SqliteUserRepository.cs
index b2b917e5e..29959bcab 100644
--- a/Emby.Server.Implementations/Data/SqliteUserRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteUserRepository.cs
@@ -93,7 +93,7 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = db.PrepareStatement("replace into users (guid, data) values (@guid, @data)"))
{
- statement.TryBind("@guid", user.Id.ToGuidParamValue());
+ statement.TryBind("@guid", user.Id.ToGuidBlob());
statement.TryBind("@data", serialized);
statement.MoveNext();
}
@@ -116,7 +116,7 @@ namespace Emby.Server.Implementations.Data
{
foreach (var row in connection.Query("select guid,data from users"))
{
- var id = row[0].ReadGuid();
+ var id = row[0].ReadGuidFromBlob();
using (var stream = _memoryStreamProvider.CreateNew(row[1].ToBlob()))
{
@@ -156,7 +156,7 @@ namespace Emby.Server.Implementations.Data
{
using (var statement = db.PrepareStatement("delete from users where guid=@id"))
{
- statement.TryBind("@id", user.Id.ToGuidParamValue());
+ statement.TryBind("@id", user.Id.ToGuidBlob());
statement.MoveNext();
}
}, TransactionMode);
diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs
index 588b42a09..b246ef196 100644
--- a/Emby.Server.Implementations/Devices/DeviceManager.cs
+++ b/Emby.Server.Implementations/Devices/DeviceManager.cs
@@ -158,7 +158,7 @@ namespace Emby.Server.Implementations.Devices
_libraryMonitor.ReportFileSystemChangeBeginning(path);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
try
{
diff --git a/Emby.Server.Implementations/Devices/DeviceRepository.cs b/Emby.Server.Implementations/Devices/DeviceRepository.cs
index f739765b3..de0dfda2e 100644
--- a/Emby.Server.Implementations/Devices/DeviceRepository.cs
+++ b/Emby.Server.Implementations/Devices/DeviceRepository.cs
@@ -46,7 +46,7 @@ namespace Emby.Server.Implementations.Devices
public Task SaveDevice(DeviceInfo device)
{
var path = Path.Combine(GetDevicePath(device.Id), "device.json");
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_syncLock)
{
@@ -180,7 +180,7 @@ namespace Emby.Server.Implementations.Devices
public void AddCameraUpload(string deviceId, LocalFileInfo file)
{
var path = Path.Combine(GetDevicePath(deviceId), "camerauploads.json");
- _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
lock (_syncLock)
{
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index d4766e1ec..b2f1f0ceb 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -308,7 +308,7 @@
<Private>True</Private>
</Reference>
<Reference Include="SQLitePCLRaw.core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1488e028ca7ab535, processorArchitecture=MSIL">
- <HintPath>..\packages\SQLitePCLRaw.core.1.1.2\lib\portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.core.dll</HintPath>
+ <HintPath>..\packages\SQLitePCLRaw.core.1.1.5\lib\portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10\SQLitePCLRaw.core.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
diff --git a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs
index 2becebb3d..3c8ad55fe 100644
--- a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs
+++ b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs
@@ -97,7 +97,7 @@ namespace Emby.Server.Implementations.FFMpeg
else
{
info = existingVersion;
- versionedDirectoryPath = Path.GetDirectoryName(info.EncoderPath);
+ versionedDirectoryPath = _fileSystem.GetDirectoryName(info.EncoderPath);
excludeFromDeletions.Add(versionedDirectoryPath);
}
}
@@ -135,7 +135,7 @@ namespace Emby.Server.Implementations.FFMpeg
{
EncoderPath = encoder,
ProbePath = probe,
- Version = Path.GetFileName(Path.GetDirectoryName(probe))
+ Version = Path.GetFileName(_fileSystem.GetDirectoryName(probe))
};
}
}
diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
index ee5245a69..5e96eda94 100644
--- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -228,7 +228,8 @@ namespace Emby.Server.Implementations.HttpServer
_streamFactory,
_enableDualModeSockets,
GetRequest,
- _fileSystem);
+ _fileSystem,
+ _environment);
}
private IHttpRequest GetRequest(HttpListenerContext httpContext)
@@ -452,6 +453,7 @@ namespace Emby.Server.Implementations.HttpServer
var date = DateTime.Now;
var httpRes = httpReq.Response;
bool enableLog = false;
+ bool logHeaders = false;
string urlToLog = null;
string remoteIp = null;
@@ -490,13 +492,14 @@ namespace Emby.Server.Implementations.HttpServer
var urlString = url.OriginalString;
enableLog = EnableLogging(urlString, localPath);
urlToLog = urlString;
+ logHeaders = enableLog && urlToLog.IndexOf("/videos/", StringComparison.OrdinalIgnoreCase) != -1;
if (enableLog)
{
urlToLog = GetUrlToLog(urlString);
remoteIp = httpReq.RemoteIp;
- LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent);
+ LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent, logHeaders ? httpReq.Headers : null);
}
if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) ||
@@ -611,7 +614,7 @@ namespace Emby.Server.Implementations.HttpServer
var duration = DateTime.Now - date;
- LoggerUtils.LogResponse(_logger, statusCode, urlToLog, remoteIp, duration);
+ LoggerUtils.LogResponse(_logger, statusCode, urlToLog, remoteIp, duration, logHeaders ? httpRes.Headers : null);
}
}
}
diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
index 687bd62b0..0af88595f 100644
--- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
@@ -353,31 +353,28 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary>
/// Pres the process optimized result.
/// </summary>
- /// <param name="requestContext">The request context.</param>
- /// <param name="responseHeaders">The responseHeaders.</param>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="cacheKeyString">The cache key string.</param>
- /// <param name="lastDateModified">The last date modified.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- /// <param name="contentType">Type of the content.</param>
- /// <returns>System.Object.</returns>
private object GetCachedResult(IRequest requestContext, IDictionary<string, string> responseHeaders, Guid cacheKey, string cacheKeyString, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType)
{
responseHeaders["ETag"] = string.Format("\"{0}\"", cacheKeyString);
- if (IsNotModified(requestContext, cacheKey, lastDateModified, cacheDuration))
+ var noCache = (requestContext.Headers.Get("Cache-Control") ?? string.Empty).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1;
+
+ if (!noCache)
{
- AddAgeHeader(responseHeaders, lastDateModified);
- AddExpiresHeader(responseHeaders, cacheKeyString, cacheDuration);
+ if (IsNotModified(requestContext, cacheKey, lastDateModified, cacheDuration))
+ {
+ AddAgeHeader(responseHeaders, lastDateModified);
+ AddExpiresHeader(responseHeaders, cacheKeyString, cacheDuration, noCache);
- var result = new HttpResult(new byte[] { }, contentType ?? "text/html", HttpStatusCode.NotModified);
+ var result = new HttpResult(new byte[] { }, contentType ?? "text/html", HttpStatusCode.NotModified);
- AddResponseHeaders(result, responseHeaders);
+ AddResponseHeaders(result, responseHeaders);
- return result;
+ return result;
+ }
}
- AddCachingHeaders(responseHeaders, cacheKeyString, lastDateModified, cacheDuration);
+ AddCachingHeaders(responseHeaders, cacheKeyString, lastDateModified, cacheDuration, noCache);
return null;
}
@@ -673,11 +670,7 @@ namespace Emby.Server.Implementations.HttpServer
/// <summary>
/// Adds the caching responseHeaders.
/// </summary>
- /// <param name="responseHeaders">The responseHeaders.</param>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="lastDateModified">The last date modified.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- private void AddCachingHeaders(IDictionary<string, string> responseHeaders, string cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration)
+ private void AddCachingHeaders(IDictionary<string, string> responseHeaders, string cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, bool noCache)
{
// Don't specify both last modified and Etag, unless caching unconditionally. They are redundant
// https://developers.google.com/speed/docs/best-practices/caching#LeverageBrowserCaching
@@ -687,11 +680,11 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders["Last-Modified"] = lastDateModified.Value.ToString("r");
}
- if (cacheDuration.HasValue)
+ if (!noCache && cacheDuration.HasValue)
{
responseHeaders["Cache-Control"] = "public, max-age=" + Convert.ToInt32(cacheDuration.Value.TotalSeconds);
}
- else if (!string.IsNullOrEmpty(cacheKey))
+ else if (!noCache && !string.IsNullOrEmpty(cacheKey))
{
responseHeaders["Cache-Control"] = "public";
}
@@ -701,18 +694,15 @@ namespace Emby.Server.Implementations.HttpServer
responseHeaders["pragma"] = "no-cache, no-store, must-revalidate";
}
- AddExpiresHeader(responseHeaders, cacheKey, cacheDuration);
+ AddExpiresHeader(responseHeaders, cacheKey, cacheDuration, noCache);
}
/// <summary>
/// Adds the expires header.
/// </summary>
- /// <param name="responseHeaders">The responseHeaders.</param>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- private void AddExpiresHeader(IDictionary<string, string> responseHeaders, string cacheKey, TimeSpan? cacheDuration)
+ private void AddExpiresHeader(IDictionary<string, string> responseHeaders, string cacheKey, TimeSpan? cacheDuration, bool noCache)
{
- if (cacheDuration.HasValue)
+ if (!noCache && cacheDuration.HasValue)
{
responseHeaders["Expires"] = DateTime.UtcNow.Add(cacheDuration.Value).ToString("r");
}
diff --git a/Emby.Server.Implementations/HttpServer/LoggerUtils.cs b/Emby.Server.Implementations/HttpServer/LoggerUtils.cs
index 8fc92a09a..f0e75eea4 100644
--- a/Emby.Server.Implementations/HttpServer/LoggerUtils.cs
+++ b/Emby.Server.Implementations/HttpServer/LoggerUtils.cs
@@ -1,6 +1,8 @@
using MediaBrowser.Model.Logging;
using System;
using System.Globalization;
+using System.Linq;
+using MediaBrowser.Model.Services;
using SocketHttpListener.Net;
namespace Emby.Server.Implementations.HttpServer
@@ -19,9 +21,18 @@ namespace Emby.Server.Implementations.HttpServer
logger.Info("{0} {1}. UserAgent: {2}", request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod, url, request.UserAgent ?? string.Empty);
}
- public static void LogRequest(ILogger logger, string url, string method, string userAgent)
+ public static void LogRequest(ILogger logger, string url, string method, string userAgent, QueryParamCollection headers)
{
- logger.Info("{0} {1}. UserAgent: {2}", "HTTP " + method, url, userAgent ?? string.Empty);
+ if (headers == null)
+ {
+ logger.Info("{0} {1}. UserAgent: {2}", "HTTP " + method, url, userAgent ?? string.Empty);
+ }
+ else
+ {
+ var headerText = string.Join(", ", headers.Select(i => i.Name + "=" + i.Value).ToArray());
+
+ logger.Info("HTTP {0} {1}. {2}", method, url, headerText);
+ }
}
/// <summary>
@@ -32,12 +43,13 @@ namespace Emby.Server.Implementations.HttpServer
/// <param name="url">The URL.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="duration">The duration.</param>
- public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration)
+ public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration, QueryParamCollection headers)
{
var durationMs = duration.TotalMilliseconds;
var logSuffix = durationMs >= 1000 && durationMs < 60000 ? "ms (slow)" : "ms";
- logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url);
+ var headerText = headers == null ? string.Empty : "Headers: " + string.Join(", ", headers.Where(i => i.Name.IndexOf("Access-", StringComparison.OrdinalIgnoreCase) == -1).Select(i => i.Name + "=" + i.Value).ToArray());
+ logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4} {5}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url, headerText);
}
}
}
diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
index b11b2fe88..682fa7a0b 100644
--- a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
+++ b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
@@ -10,6 +10,7 @@ using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Services;
+using MediaBrowser.Model.System;
using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives;
@@ -30,8 +31,9 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
private readonly IFileSystem _fileSystem;
private readonly Func<HttpListenerContext, IHttpRequest> _httpRequestFactory;
private readonly bool _enableDualMode;
+ private readonly IEnvironmentInfo _environment;
- public WebSocketSharpListener(ILogger logger, ICertificate certificate, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, bool enableDualMode, Func<HttpListenerContext, IHttpRequest> httpRequestFactory, IFileSystem fileSystem)
+ public WebSocketSharpListener(ILogger logger, ICertificate certificate, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, bool enableDualMode, Func<HttpListenerContext, IHttpRequest> httpRequestFactory, IFileSystem fileSystem, IEnvironmentInfo environment)
{
_logger = logger;
_certificate = certificate;
@@ -44,6 +46,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
_enableDualMode = enableDualMode;
_httpRequestFactory = httpRequestFactory;
_fileSystem = fileSystem;
+ _environment = environment;
}
public Action<Exception, IRequest, bool> ErrorHandler { get; set; }
@@ -56,7 +59,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
public void Start(IEnumerable<string> urlPrefixes)
{
if (_listener == null)
- _listener = new HttpListener(_logger, _cryptoProvider, _streamFactory, _socketFactory, _networkManager, _textEncoding, _memoryStreamProvider, _fileSystem);
+ _listener = new HttpListener(_logger, _cryptoProvider, _streamFactory, _socketFactory, _networkManager, _textEncoding, _memoryStreamProvider, _fileSystem, _environment);
_listener.EnableDualMode = _enableDualMode;
diff --git a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs
index fd30b227f..9e58ee57c 100644
--- a/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs
+++ b/Emby.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs
@@ -7,6 +7,7 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Services;
using SocketHttpListener.Net;
using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse;
using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
@@ -66,6 +67,14 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
_response.AddHeader(name, value);
}
+ public QueryParamCollection Headers
+ {
+ get
+ {
+ return _response.Headers;
+ }
+ }
+
public string GetHeader(string name)
{
return _response.Headers[name];
diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs
index 033cbd8b0..edff25156 100644
--- a/Emby.Server.Implementations/IO/FileRefresher.cs
+++ b/Emby.Server.Implementations/IO/FileRefresher.cs
@@ -34,8 +34,9 @@ namespace Emby.Server.Implementations.IO
public event EventHandler<EventArgs> Completed;
private readonly IEnvironmentInfo _environmentInfo;
+ private readonly ILibraryManager _libraryManager;
- public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger, ITimerFactory timerFactory, IEnvironmentInfo environmentInfo)
+ public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger, ITimerFactory timerFactory, IEnvironmentInfo environmentInfo, ILibraryManager libraryManager1)
{
logger.Debug("New file refresher created for {0}", path);
Path = path;
@@ -47,6 +48,7 @@ namespace Emby.Server.Implementations.IO
Logger = logger;
_timerFactory = timerFactory;
_environmentInfo = environmentInfo;
+ _libraryManager = libraryManager1;
AddPath(path);
}
@@ -235,6 +237,12 @@ namespace Emby.Server.Implementations.IO
return false;
}
+ // Only try to open video files
+ if (!_libraryManager.IsVideoFile(path))
+ {
+ return false;
+ }
+
try
{
var data = _fileSystem.GetFileSystemInfo(path);
diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs
index 2677f7b2a..b2ec84a82 100644
--- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs
+++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs
@@ -258,7 +258,7 @@ namespace Emby.Server.Implementations.Images
{
return await CreateSquareCollage(item, itemsWithImages, outputPath).ConfigureAwait(false);
}
- if (item is Playlist || item is MusicGenre || item is Genre || item is GameGenre)
+ if (item is Playlist || item is MusicGenre || item is Genre || item is GameGenre || item is PhotoAlbum)
{
return await CreateSquareCollage(item, itemsWithImages, outputPath).ConfigureAwait(false);
}
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 685c794b7..3c94f9784 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1197,6 +1197,7 @@ namespace Emby.Server.Implementations.Library
catch (OperationCanceledException)
{
_logger.Info("Post-scan task cancelled: {0}", task.GetType().Name);
+ throw;
}
catch (Exception ex)
{
diff --git a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs
index 643c5970e..d4be2dabe 100644
--- a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs
@@ -63,7 +63,7 @@ namespace Emby.Server.Implementations.Library.Validators
catch (OperationCanceledException)
{
// Don't clutter the log
- break;
+ throw;
}
catch (Exception ex)
{
diff --git a/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs b/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs
index b1820bb91..f7fbb9331 100644
--- a/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs
@@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.Library.Validators
catch (OperationCanceledException)
{
// Don't clutter the log
- break;
+ throw;
}
catch (Exception ex)
{
diff --git a/Emby.Server.Implementations/Library/Validators/GenresValidator.cs b/Emby.Server.Implementations/Library/Validators/GenresValidator.cs
index d8956f78a..d71e77a9a 100644
--- a/Emby.Server.Implementations/Library/Validators/GenresValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/GenresValidator.cs
@@ -54,7 +54,7 @@ namespace Emby.Server.Implementations.Library.Validators
catch (OperationCanceledException)
{
// Don't clutter the log
- break;
+ throw;
}
catch (Exception ex)
{
diff --git a/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs b/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs
index 983c881b7..98d53c125 100644
--- a/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs
@@ -54,7 +54,7 @@ namespace Emby.Server.Implementations.Library.Validators
catch (OperationCanceledException)
{
// Don't clutter the log
- break;
+ throw;
}
catch (Exception ex)
{
diff --git a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs
index 6faab7bb9..97b8ff0ac 100644
--- a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs
@@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.Library.Validators
catch (OperationCanceledException)
{
// Don't clutter the log
- break;
+ throw;
}
catch (Exception ex)
{
diff --git a/Emby.Server.Implementations/Library/Validators/YearsPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/YearsPostScanTask.cs
index ae43c77f0..4afb4c04a 100644
--- a/Emby.Server.Implementations/Library/Validators/YearsPostScanTask.cs
+++ b/Emby.Server.Implementations/Library/Validators/YearsPostScanTask.cs
@@ -26,6 +26,8 @@ namespace Emby.Server.Implementations.Library.Validators
while (yearNumber < maxYear)
{
+ cancellationToken.ThrowIfCancellationRequested();
+
try
{
var year = _libraryManager.GetYear(yearNumber);
@@ -35,7 +37,7 @@ namespace Emby.Server.Implementations.Library.Validators
catch (OperationCanceledException)
{
// Don't clutter the log
- break;
+ throw;
}
catch (Exception ex)
{
diff --git a/Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs b/Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs
index 76c7a7d77..40752db80 100644
--- a/Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs
+++ b/Emby.Server.Implementations/Notifications/SqliteNotificationsRepository.cs
@@ -81,7 +81,7 @@ namespace Emby.Server.Implementations.Notifications
}
clauses.Add("UserId=?");
- paramList.Add(query.UserId.ToGuidParamValue());
+ paramList.Add(query.UserId.ToGuidBlob());
var whereClause = " where " + string.Join(" And ", clauses.ToArray());
@@ -133,7 +133,7 @@ namespace Emby.Server.Implementations.Notifications
using (var statement = connection.PrepareStatement("select Level from Notifications where UserId=@UserId and IsRead=@IsRead"))
{
statement.TryBind("@IsRead", false);
- statement.TryBind("@UserId", userId.ToGuidParamValue());
+ statement.TryBind("@UserId", userId.ToGuidBlob());
var levels = new List<NotificationLevel>();
@@ -159,8 +159,8 @@ namespace Emby.Server.Implementations.Notifications
{
var notification = new Notification
{
- Id = reader[0].ReadGuid().ToString("N"),
- UserId = reader[1].ReadGuid().ToString("N"),
+ Id = reader[0].ReadGuidFromBlob().ToString("N"),
+ UserId = reader[1].ReadGuidFromBlob().ToString("N"),
Date = reader[2].ReadDateTime(),
Name = reader[3].ToString()
};
@@ -251,8 +251,8 @@ namespace Emby.Server.Implementations.Notifications
{
using (var statement = conn.PrepareStatement("replace into Notifications (Id, UserId, Date, Name, Description, Url, Level, IsRead, Category, RelatedId) values (@Id, @UserId, @Date, @Name, @Description, @Url, @Level, @IsRead, @Category, @RelatedId)"))
{
- statement.TryBind("@Id", notification.Id.ToGuidParamValue());
- statement.TryBind("@UserId", notification.UserId.ToGuidParamValue());
+ statement.TryBind("@Id", notification.Id.ToGuidBlob());
+ statement.TryBind("@UserId", notification.UserId.ToGuidBlob());
statement.TryBind("@Date", notification.Date.ToDateTimeParamValue());
statement.TryBind("@Name", notification.Name);
statement.TryBind("@Description", notification.Description);
@@ -315,7 +315,7 @@ namespace Emby.Server.Implementations.Notifications
using (var statement = conn.PrepareStatement("update Notifications set IsRead=@IsRead where UserId=@UserId"))
{
statement.TryBind("@IsRead", isRead);
- statement.TryBind("@UserId", userId.ToGuidParamValue());
+ statement.TryBind("@UserId", userId.ToGuidBlob());
statement.MoveNext();
}
@@ -337,13 +337,13 @@ namespace Emby.Server.Implementations.Notifications
using (var statement = conn.PrepareStatement("update Notifications set IsRead=@IsRead where UserId=@UserId and Id=@Id"))
{
statement.TryBind("@IsRead", isRead);
- statement.TryBind("@UserId", userId.ToGuidParamValue());
+ statement.TryBind("@UserId", userId.ToGuidBlob());
foreach (var id in notificationIdList)
{
statement.Reset();
- statement.TryBind("@Id", id.ToGuidParamValue());
+ statement.TryBind("@Id", id.ToGuidBlob());
statement.MoveNext();
}
diff --git a/Emby.Server.Implementations/Security/AuthenticationRepository.cs b/Emby.Server.Implementations/Security/AuthenticationRepository.cs
index a2d61873b..9ec0af6bb 100644
--- a/Emby.Server.Implementations/Security/AuthenticationRepository.cs
+++ b/Emby.Server.Implementations/Security/AuthenticationRepository.cs
@@ -74,7 +74,7 @@ namespace Emby.Server.Implementations.Security
{
using (var statement = db.PrepareStatement("replace into AccessTokens (Id, AccessToken, DeviceId, AppName, AppVersion, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @AppVersion, @DeviceName, @UserId, @IsActive, @DateCreated, @DateRevoked)"))
{
- statement.TryBind("@Id", info.Id.ToGuidParamValue());
+ statement.TryBind("@Id", info.Id.ToGuidBlob());
statement.TryBind("@AccessToken", info.AccessToken);
statement.TryBind("@DeviceId", info.DeviceId);
@@ -259,7 +259,7 @@ namespace Emby.Server.Implementations.Security
using (var statement = connection.PrepareStatement(commandText))
{
- statement.BindParameters["@Id"].Bind(id.ToGuidParamValue());
+ statement.BindParameters["@Id"].Bind(id.ToGuidBlob());
foreach (var row in statement.ExecuteQuery())
{
@@ -275,7 +275,7 @@ namespace Emby.Server.Implementations.Security
{
var info = new AuthenticationInfo
{
- Id = reader[0].ReadGuid().ToString("N"),
+ Id = reader[0].ReadGuidFromBlob().ToString("N"),
AccessToken = reader[1].ToString()
};
diff --git a/Emby.Server.Implementations/Social/SharingRepository.cs b/Emby.Server.Implementations/Social/SharingRepository.cs
index e8230947e..46e9205bb 100644
--- a/Emby.Server.Implementations/Social/SharingRepository.cs
+++ b/Emby.Server.Implementations/Social/SharingRepository.cs
@@ -61,7 +61,7 @@ namespace Emby.Server.Implementations.Social
var commandText = "replace into Shares (Id, ItemId, UserId, ExpirationDate) values (?, ?, ?, ?)";
db.Execute(commandText,
- info.Id.ToGuidParamValue(),
+ info.Id.ToGuidBlob(),
info.ItemId,
info.UserId,
info.ExpirationDate.ToDateTimeParamValue());
@@ -84,7 +84,7 @@ namespace Emby.Server.Implementations.Social
var commandText = "select Id, ItemId, UserId, ExpirationDate from Shares where id = ?";
var paramList = new List<object>();
- paramList.Add(id.ToGuidParamValue());
+ paramList.Add(id.ToGuidBlob());
foreach (var row in connection.Query(commandText, paramList.ToArray()))
{
@@ -100,7 +100,7 @@ namespace Emby.Server.Implementations.Social
{
var info = new SocialShareInfo();
- info.Id = reader[0].ReadGuid().ToString("N");
+ info.Id = reader[0].ReadGuidFromBlob().ToString("N");
info.ItemId = reader[1].ToString();
info.UserId = reader[2].ToString();
info.ExpirationDate = reader[3].ReadDateTime();
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index 57019cc4e..e7aa402f2 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/Emby.Server.Implementations/Updates/InstallationManager.cs
@@ -664,9 +664,19 @@ namespace Emby.Server.Implementations.Updates
// Remove it the quick way for now
_applicationHost.RemovePlugin(plugin);
- _logger.Info("Deleting plugin file {0}", plugin.AssemblyFilePath);
+ var path = plugin.AssemblyFilePath;
+ _logger.Info("Deleting plugin file {0}", path);
- _fileSystem.DeleteFile(plugin.AssemblyFilePath);
+ // Make this case-insensitive to account for possible incorrect assembly naming
+ var file = _fileSystem.GetFilePaths(path)
+ .FirstOrDefault(i => string.Equals(i, path, StringComparison.OrdinalIgnoreCase));
+
+ if (!string.IsNullOrWhiteSpace(file))
+ {
+ path = file;
+ }
+
+ _fileSystem.DeleteFile(path);
OnPluginUninstalled(plugin);
diff --git a/Emby.Server.Implementations/packages.config b/Emby.Server.Implementations/packages.config
index e4c75e1e9..5ce754d3f 100644
--- a/Emby.Server.Implementations/packages.config
+++ b/Emby.Server.Implementations/packages.config
@@ -3,5 +3,5 @@
<package id="Emby.XmlTv" version="1.0.8" targetFramework="portable45-net45+win8" />
<package id="MediaBrowser.Naming" version="1.0.5" targetFramework="portable45-net45+win8" />
<package id="SQLitePCL.pretty" version="1.1.0" targetFramework="portable45-net45+win8" />
- <package id="SQLitePCLRaw.core" version="1.1.2" targetFramework="portable45-net45+win8" />
+ <package id="SQLitePCLRaw.core" version="1.1.5" targetFramework="portable45-net45+win8" />
</packages> \ No newline at end of file
diff --git a/Emby.Server.sln b/Emby.Server.sln
index c6e057c42..002a7ae0e 100644
--- a/Emby.Server.sln
+++ b/Emby.Server.sln
@@ -54,8 +54,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Emby.Server.Core", "Emby.Se
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing", "Emby.Drawing\Emby.Drawing.csproj", "{08FFF49B-F175-4807-A2B5-73B0EBD9F716}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack", "ServiceStack\ServiceStack.csproj", "{680A1709-25EB-4D52-A87F-EE03FFD94BAA}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SocketHttpListener.Portable", "SocketHttpListener.Portable\SocketHttpListener.Portable.csproj", "{4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}"
EndProject
Global
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 0785b904a..ff7749795 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -82,10 +82,6 @@
<Compile Include="Reports\Model\ReportRow.cs" />
<Compile Include="Reports\ReportRequests.cs" />
<Compile Include="Reports\ReportsService.cs" />
- <Compile Include="Reports\Stat\ReportStatBuilder.cs" />
- <Compile Include="Reports\Stat\ReportStatGroup.cs" />
- <Compile Include="Reports\Stat\ReportStatItem.cs" />
- <Compile Include="Reports\Stat\ReportStatResult.cs" />
<Compile Include="Social\SharingService.cs" />
<Compile Include="StartupWizardService.cs" />
<Compile Include="Subtitles\SubtitleService.cs" />
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index daec00e10..67921ab34 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -671,12 +671,15 @@ namespace MediaBrowser.Api.Playback
request.AudioCodec = EncodingHelper.InferAudioCodec(url);
}
+ var enableDlnaHeaders = !string.IsNullOrWhiteSpace(request.Params) /*||
+ string.Equals(Request.Headers.Get("GetContentFeatures.DLNA.ORG"), "1", StringComparison.OrdinalIgnoreCase)*/;
+
var state = new StreamState(MediaSourceManager, Logger, TranscodingJobType)
{
Request = request,
RequestedUrl = url,
UserAgent = Request.UserAgent,
- EnableDlnaHeaders = !string.IsNullOrWhiteSpace(request.Params)
+ EnableDlnaHeaders = enableDlnaHeaders
};
var auth = AuthorizationContext.GetAuthorizationInfo(Request);
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 0fe1e533d..d64c009a0 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -879,7 +879,7 @@ namespace MediaBrowser.Api.Playback.Hls
// Add resolution params, if specified
if (!hasGraphicalSubs)
{
- args += EncodingHelper.GetOutputSizeParam(state, codec, EnableCopyTs(state));
+ args += EncodingHelper.GetOutputSizeParam(state, codec, true);
}
// This is for internal graphical subs
@@ -891,7 +891,7 @@ namespace MediaBrowser.Api.Playback.Hls
//args += " -flags -global_header";
}
- if (EnableCopyTs(state) && args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
+ if (args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
{
args += " -copyts";
}
@@ -901,13 +901,9 @@ namespace MediaBrowser.Api.Playback.Hls
args += " -vsync " + state.OutputVideoSync;
}
- return args;
- }
+ args += EncodingHelper.GetOutputFFlags(state);
- private bool EnableCopyTs(StreamState state)
- {
- //return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
- return true;
+ return args;
}
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index 22c6202e4..e32970be5 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -124,6 +124,8 @@ namespace MediaBrowser.Api.Playback.Hls
args += " -vsync " + state.OutputVideoSync;
}
+ args += EncodingHelper.GetOutputFFlags(state);
+
return args;
}
diff --git a/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs b/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs
index b25123df8..e25e78802 100644
--- a/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs
+++ b/MediaBrowser.Api/Reports/Common/HeaderMetadata.cs
@@ -35,7 +35,8 @@ namespace MediaBrowser.Api.Reports
Tracks,
EpisodeSeries,
EpisodeSeason,
- AudioAlbumArtist,
+ EpisodeNumber,
+ AudioAlbumArtist,
MusicArtist,
AudioAlbum,
Locked,
diff --git a/MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs b/MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs
index 39b2610d5..6d5a180fb 100644
--- a/MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs
+++ b/MediaBrowser.Api/Reports/Common/ReportBuilderBase.cs
@@ -148,6 +148,11 @@ namespace MediaBrowser.Api.Reports
/// <returns> The localized header. </returns>
protected static string GetLocalizedHeader(HeaderMetadata internalHeader)
{
+ if (internalHeader == HeaderMetadata.EpisodeNumber)
+ {
+ return "Episode";
+ }
+
string headerName = "";
if (internalHeader != HeaderMetadata.None)
{
diff --git a/MediaBrowser.Api/Reports/Data/ReportBuilder.cs b/MediaBrowser.Api/Reports/Data/ReportBuilder.cs
index c9c63847c..9c3dde6a4 100644
--- a/MediaBrowser.Api/Reports/Data/ReportBuilder.cs
+++ b/MediaBrowser.Api/Reports/Data/ReportBuilder.cs
@@ -102,7 +102,7 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.Series,
HeaderMetadata.Season,
HeaderMetadata.SeasonNumber,
- HeaderMetadata.DateAdded,
+ HeaderMetadata.DateAdded,
HeaderMetadata.Year,
HeaderMetadata.Genres
};
@@ -269,10 +269,11 @@ namespace MediaBrowser.Api.Reports
HeaderMetadata.ImagePrimary,
HeaderMetadata.ImageBackdrop,
HeaderMetadata.ImageLogo,
- HeaderMetadata.Name,
+ HeaderMetadata.Name,
HeaderMetadata.EpisodeSeries,
HeaderMetadata.Season,
- HeaderMetadata.DateAdded,
+ HeaderMetadata.EpisodeNumber,
+ HeaderMetadata.DateAdded,
HeaderMetadata.ReleaseDate,
HeaderMetadata.Year,
HeaderMetadata.Genres,
@@ -450,6 +451,12 @@ namespace MediaBrowser.Api.Reports
internalHeader = HeaderMetadata.Season;
break;
+ case HeaderMetadata.EpisodeNumber:
+ option.Column = (i, r) => this.GetObject<BaseItem, string>(i, (x) => x.IndexNumber == null ? "" : x.IndexNumber.ToString());
+ //option.Header.SortField = "IndexNumber";
+ //option.Header.HeaderFieldType = ReportFieldType.Int;
+ break;
+
case HeaderMetadata.Network:
option.Column = (i, r) => this.GetListAsString(i.Studios);
option.ItemID = (i) => this.GetStudioID(i.Studios.FirstOrDefault());
diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs b/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs
deleted file mode 100644
index 52b095dee..000000000
--- a/MediaBrowser.Api/Reports/Stat/ReportStatBuilder.cs
+++ /dev/null
@@ -1,256 +0,0 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace MediaBrowser.Api.Reports
-{
- /// <summary> A report stat builder. </summary>
- /// <seealso cref="T:MediaBrowser.Api.Reports.ReportBuilderBase"/>
- public class ReportStatBuilder : ReportBuilderBase
- {
- #region [Constructors]
-
- /// <summary>
- /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatBuilder class. </summary>
- /// <param name="libraryManager"> Manager for library. </param>
- public ReportStatBuilder(ILibraryManager libraryManager)
- : base(libraryManager)
- {
- }
-
- #endregion
-
- #region [Public Methods]
-
- /// <summary> Gets report stat result. </summary>
- /// <param name="items"> The items. </param>
- /// <param name="reportIncludeItemTypes"> List of types of the report include items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The report stat result. </returns>
- public ReportStatResult GetResult(BaseItem[] items, ReportIncludeItemTypes reportIncludeItemTypes, int topItem = 5)
- {
- ReportStatResult result = new ReportStatResult();
- result = this.GetResultGenres(result, items, topItem);
- result = this.GetResultStudios(result, items, topItem);
- result = this.GetResultPersons(result, items, topItem);
- result = this.GetResultProductionYears(result, items, topItem);
- result = this.GetResultCommunityRatings(result, items, topItem);
- result = this.GetResultParentalRatings(result, items, topItem);
-
- switch (reportIncludeItemTypes)
- {
- case ReportIncludeItemTypes.Season:
- case ReportIncludeItemTypes.Series:
- case ReportIncludeItemTypes.MusicAlbum:
- case ReportIncludeItemTypes.MusicArtist:
- case ReportIncludeItemTypes.Game:
- break;
- case ReportIncludeItemTypes.Movie:
- case ReportIncludeItemTypes.BoxSet:
-
- break;
- case ReportIncludeItemTypes.Book:
- case ReportIncludeItemTypes.Episode:
- case ReportIncludeItemTypes.Video:
- case ReportIncludeItemTypes.MusicVideo:
- case ReportIncludeItemTypes.Trailer:
- case ReportIncludeItemTypes.Audio:
- case ReportIncludeItemTypes.BaseItem:
- default:
- break;
- }
-
- result.Groups = result.Groups.OrderByDescending(n => n.Items.Count()).ToList();
-
- return result;
- }
-
- #endregion
-
- #region [Protected Internal Methods]
- /// <summary> Gets the headers. </summary>
- /// <typeparam name="H"> Type of the header. </typeparam>
- /// <param name="request"> The request. </param>
- /// <returns> The headers. </returns>
- /// <seealso cref="M:MediaBrowser.Api.Reports.ReportBuilderBase.GetHeaders{H}(H)"/>
- protected internal override List<ReportHeader> GetHeaders<H>(H request)
- {
- throw new NotImplementedException();
- }
-
- #endregion
-
- #region [Private Methods]
-
- /// <summary> Gets the groups. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="header"> The header. </param>
- /// <param name="topItem"> The top item. </param>
- /// <param name="top"> The top. </param>
- private void GetGroups(ReportStatResult result, string header, int topItem, IEnumerable<ReportStatItem> top)
- {
- if (top != null && top.Count() > 0)
- {
- var group = new ReportStatGroup { Header = ReportStatGroup.FormatedHeader(header, topItem) };
- group.Items.AddRange(top);
- result.Groups.Add(group);
- }
- }
-
- /// <summary> Gets result community ratings. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result community ratings. </returns>
- private ReportStatResult GetResultCommunityRatings(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.CommunityRating), topItem,
- items.Where(x => x.CommunityRating != null && x.CommunityRating > 0)
- .GroupBy(x => x.CommunityRating)
- .OrderByDescending(x => x.Count())
- .Take(topItem)
- .Select(x => new ReportStatItem
- {
- Name = x.Key.ToString(),
- Value = x.Count().ToString()
- })
- );
-
- return result;
- }
-
- /// <summary> Gets result genres. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result genres. </returns>
- private ReportStatResult GetResultGenres(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Genres), topItem,
- items.SelectMany(x => x.Genres)
- .GroupBy(x => x)
- .OrderByDescending(x => x.Count())
- .Take(topItem)
- .Select(x => new ReportStatItem
- {
- Name = x.Key,
- Value = x.Count().ToString(),
- Id = GetGenreID(x.Key)
- }));
- return result;
-
- }
-
- /// <summary> Gets result parental ratings. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result parental ratings. </returns>
- private ReportStatResult GetResultParentalRatings(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.ParentalRatings), topItem,
- items.Where(x => x.OfficialRating != null)
- .GroupBy(x => x.OfficialRating)
- .OrderByDescending(x => x.Count())
- .Take(topItem)
- .Select(x => new ReportStatItem
- {
- Name = x.Key.ToString(),
- Value = x.Count().ToString()
- })
- );
-
- return result;
- }
-
- /// <summary> Gets result persons. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result persons. </returns>
- private ReportStatResult GetResultPersons(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- List<HeaderMetadata> t = new List<HeaderMetadata>
- {
- HeaderMetadata.Actor,
- HeaderMetadata.Composer,
- HeaderMetadata.Director,
- HeaderMetadata.GuestStar,
- HeaderMetadata.Producer,
- HeaderMetadata.Writer,
- HeaderMetadata.Artist,
- HeaderMetadata.AlbumArtist
- };
- foreach (var item in t)
- {
- var ps = items.SelectMany(x => _libraryManager.GetPeople(x))
- .Where(n => n.Type == item.ToString())
- .GroupBy(x => x.Name)
- .OrderByDescending(x => x.Count())
- .Take(topItem);
- if (ps != null && ps.Count() > 0)
- this.GetGroups(result, GetLocalizedHeader(item), topItem,
- ps.Select(x => new ReportStatItem
- {
- Name = x.Key,
- Value = x.Count().ToString(),
- Id = GetPersonID(x.Key)
- })
- );
- }
-
- return result;
- }
-
- /// <summary> Gets result production years. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result production years. </returns>
- private ReportStatResult GetResultProductionYears(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Year), topItem,
- items.Where(x => x.ProductionYear != null && x.ProductionYear > 0)
- .GroupBy(x => x.ProductionYear)
- .OrderByDescending(x => x.Count())
- .Take(topItem)
- .Select(x => new ReportStatItem
- {
- Name = x.Key.ToString(),
- Value = x.Count().ToString()
- })
- );
-
- return result;
- }
-
- /// <summary> Gets result studios. </summary>
- /// <param name="result"> The result. </param>
- /// <param name="items"> The items. </param>
- /// <param name="topItem"> The top item. </param>
- /// <returns> The result studios. </returns>
- private ReportStatResult GetResultStudios(ReportStatResult result, BaseItem[] items, int topItem = 5)
- {
- this.GetGroups(result, GetLocalizedHeader(HeaderMetadata.Studios), topItem,
- items.SelectMany(x => x.Studios)
- .GroupBy(x => x)
- .OrderByDescending(x => x.Count())
- .Take(topItem)
- .Select(x => new ReportStatItem
- {
- Name = x.Key,
- Value = x.Count().ToString(),
- Id = GetStudioID(x.Key)
- })
- );
-
- return result;
-
- }
-
- #endregion
-
- }
-}
diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatGroup.cs b/MediaBrowser.Api/Reports/Stat/ReportStatGroup.cs
deleted file mode 100644
index f901b5417..000000000
--- a/MediaBrowser.Api/Reports/Stat/ReportStatGroup.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.Collections.Generic;
-
-namespace MediaBrowser.Api.Reports
-{
- /// <summary> A report stat group. </summary>
- public class ReportStatGroup
- {
- /// <summary>
- /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatGroup class. </summary>
- public ReportStatGroup()
- {
- Items = new List<ReportStatItem>();
- TotalRecordCount = 0;
- }
-
- /// <summary> Gets or sets the header. </summary>
- /// <value> The header. </value>
- public string Header { get; set; }
-
- /// <summary> Gets or sets the items. </summary>
- /// <value> The items. </value>
- public List<ReportStatItem> Items { get; set; }
-
- /// <summary> Gets or sets the number of total records. </summary>
- /// <value> The total number of record count. </value>
- public int TotalRecordCount { get; set; }
-
- internal static string FormatedHeader(string header, int topItem)
- {
- return string.Format("Top {0} {1}", topItem, header);
- }
- }
-}
diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatItem.cs b/MediaBrowser.Api/Reports/Stat/ReportStatItem.cs
deleted file mode 100644
index c93ba15af..000000000
--- a/MediaBrowser.Api/Reports/Stat/ReportStatItem.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace MediaBrowser.Api.Reports
-{
- /// <summary> A report stat item. </summary>
- public class ReportStatItem
- {
- /// <summary> Gets or sets the name. </summary>
- /// <value> The name. </value>
- public string Name { get; set; }
-
- /// <summary> Gets or sets the image. </summary>
- /// <value> The image. </value>
- public string Image { get; set; }
-
- /// <summary> Gets or sets the value. </summary>
- /// <value> The value. </value>
- public string Value { get; set; }
-
- /// <summary> Gets or sets the identifier. </summary>
- /// <value> The identifier. </value>
- public string Id { get; set; }
-
- }
-}
diff --git a/MediaBrowser.Api/Reports/Stat/ReportStatResult.cs b/MediaBrowser.Api/Reports/Stat/ReportStatResult.cs
deleted file mode 100644
index fbf98fc17..000000000
--- a/MediaBrowser.Api/Reports/Stat/ReportStatResult.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System.Collections.Generic;
-
-namespace MediaBrowser.Api.Reports
-{
- /// <summary> Encapsulates the result of a report stat. </summary>
- public class ReportStatResult
- {
- /// <summary>
- /// Initializes a new instance of the MediaBrowser.Api.Reports.ReportStatResult class. </summary>
- public ReportStatResult()
- {
- Groups = new List<ReportStatGroup>();
- TotalRecordCount = 0;
- }
-
- /// <summary> Gets or sets the groups. </summary>
- /// <value> The groups. </value>
- public List<ReportStatGroup> Groups { get; set; }
-
- /// <summary> Gets or sets the number of total records. </summary>
- /// <value> The total number of record count. </value>
- public int TotalRecordCount { get; set; }
- }
-}
diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
index de1909e54..830093fcf 100644
--- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs
+++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
@@ -16,12 +16,6 @@ namespace MediaBrowser.Controller.Drawing
/// <value>The supported output formats.</value>
ImageFormat[] SupportedOutputFormats { get; }
/// <summary>
- /// Crops the white space.
- /// </summary>
- /// <param name="inputPath">The input path.</param>
- /// <param name="outputPath">The output path.</param>
- void CropWhiteSpace(string inputPath, string outputPath);
- /// <summary>
/// Encodes the image.
/// </summary>
/// <param name="inputPath">The input path.</param>
@@ -56,5 +50,7 @@ namespace MediaBrowser.Controller.Drawing
/// </summary>
/// <value><c>true</c> if [supports image encoding]; otherwise, <c>false</c>.</value>
bool SupportsImageEncoding { get; }
+
+ ImageSize GetImageSize(string path);
}
}
diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
index 19f391b4a..a107c1232 100644
--- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs
+++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
@@ -112,5 +112,7 @@ namespace MediaBrowser.Controller.Drawing
/// </summary>
/// <value><c>true</c> if [supports image collage creation]; otherwise, <c>false</c>.</value>
bool SupportsImageCollageCreation { get; }
+
+ IImageEncoder ImageEncoder { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
index f4b3d9455..70ac08343 100644
--- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
+++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
@@ -86,6 +86,7 @@ namespace MediaBrowser.Controller.Drawing
PercentPlayed.Equals(0) &&
!UnplayedCount.HasValue &&
!Blur.HasValue &&
+ !CropWhiteSpace &&
string.IsNullOrEmpty(BackgroundColor) &&
string.IsNullOrEmpty(ForegroundLayer);
}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index ca0b97a9f..11311905c 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -1306,7 +1306,8 @@ namespace MediaBrowser.Controller.MediaEncoding
filters.Add("format=nv12|vaapi");
filters.Add("hwupload");
}
- else if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
+
+ if (state.DeInterlace && !string.Equals(outputVideoCodec, "h264_vaapi", StringComparison.OrdinalIgnoreCase))
{
filters.Add("yadif=0:-1:0");
}
@@ -1533,14 +1534,26 @@ namespace MediaBrowser.Controller.MediaEncoding
}
var flags = new List<string>();
- if (state.IgnoreDts)
+ if (state.IgnoreInputDts)
{
flags.Add("+igndts");
}
- if (state.IgnoreIndex)
+ if (state.IgnoreInputIndex)
{
flags.Add("+ignidx");
}
+ if (state.GenPtsInput)
+ {
+ flags.Add("+genpts");
+ }
+ if (state.DiscardCorruptFramesInput)
+ {
+ flags.Add("+discardcorrupt");
+ }
+ if (state.EnableFastSeekInput)
+ {
+ flags.Add("+fastseek");
+ }
if (flags.Count > 0)
{
@@ -1864,6 +1877,22 @@ namespace MediaBrowser.Controller.MediaEncoding
).Trim();
}
+ public string GetOutputFFlags(EncodingJobInfo state)
+ {
+ var flags = new List<string>();
+ if (state.GenPtsOutput)
+ {
+ flags.Add("+genpts");
+ }
+
+ if (flags.Count > 0)
+ {
+ return " -fflags " + string.Join("", flags.ToArray());
+ }
+
+ return string.Empty;
+ }
+
public string GetProgressiveVideoArguments(EncodingJobInfo state, EncodingOptions encodingOptions, string videoCodec, string defaultH264Preset)
{
var args = "-codec:v:0 " + videoCodec;
@@ -1943,6 +1972,8 @@ namespace MediaBrowser.Controller.MediaEncoding
args += " -vsync " + state.OutputVideoSync;
}
+ args += GetOutputFFlags(state);
+
return args;
}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
index 28ada9dae..409dec482 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
@@ -39,14 +39,52 @@ namespace MediaBrowser.Controller.MediaEncoding
public bool ReadInputAtNativeFramerate { get; set; }
- public bool IgnoreDts
+ public bool IgnoreInputDts
{
- get { return MediaSource.IgnoreDts; }
+ get
+ {
+ return MediaSource.IgnoreDts;
+ }
+ }
+
+ public bool IgnoreInputIndex
+ {
+ get
+ {
+ return MediaSource.IgnoreIndex;
+ }
+ }
+
+ public bool GenPtsInput
+ {
+ get
+ {
+ return false;
+ }
}
- public bool IgnoreIndex
+ public bool DiscardCorruptFramesInput
{
- get { return MediaSource.IgnoreIndex; }
+ get
+ {
+ return false;
+ }
+ }
+
+ public bool EnableFastSeekInput
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public bool GenPtsOutput
+ {
+ get
+ {
+ return false;
+ }
}
public string OutputContainer { get; set; }
diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
index a3a55176c..57e2ec450 100644
--- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
@@ -218,13 +218,9 @@ namespace MediaBrowser.LocalMetadata.Savers
{
if (file.IsHidden)
{
- FileSystem.SetHidden(path, false);
wasHidden = true;
}
- if (file.IsReadOnly)
- {
- FileSystem.SetReadOnly(path, false);
- }
+ FileSystem.SetAttributes(path, false, false);
}
using (var filestream = FileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
index 15221c2ac..27f66835f 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs
@@ -50,10 +50,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
return false;
}
- if (logOutput)
- {
- _logger.Info("ffmpeg info: {0}", output);
- }
+ _logger.Info("ffmpeg info: {0}", output);
if (output.IndexOf("Libav developers", StringComparison.OrdinalIgnoreCase) != -1)
{
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index 8b20dca1b..6270b87c6 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -176,6 +176,14 @@ namespace MediaBrowser.MediaEncoding.Probing
info.Video3DFormat = Video3DFormat.FullSideBySide;
}
+ foreach (var mediaStream in info.MediaStreams)
+ {
+ if (mediaStream.Type == MediaStreamType.Audio && !mediaStream.BitRate.HasValue)
+ {
+ mediaStream.BitRate = GetEstimatedAudioBitrate(mediaStream.Codec, mediaStream.Channels);
+ }
+ }
+
var videoStreamsBitrate = info.MediaStreams.Where(i => i.Type == MediaStreamType.Video).Select(i => i.BitRate ?? 0).Sum();
// If ffprobe reported the container bitrate as being the same as the video stream bitrate, then it's wrong
if (videoStreamsBitrate == (info.Bitrate ?? 0))
@@ -187,6 +195,32 @@ namespace MediaBrowser.MediaEncoding.Probing
return info;
}
+ private int? GetEstimatedAudioBitrate(string codec, int? channels)
+ {
+ if (!channels.HasValue)
+ {
+ return null;
+ }
+
+ var channelsValue = channels.Value;
+
+ if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase))
+ {
+ if (channelsValue <= 2)
+ {
+ return 192000;
+ }
+
+ if (channelsValue >= 5)
+ {
+ return 320000;
+ }
+ }
+
+ return null;
+ }
+
private void FetchFromItunesInfo(string xml, MediaInfo info)
{
// Make things simpler and strip out the dtd
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 838111a38..60bbf6240 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -55,6 +55,7 @@ namespace MediaBrowser.Model.Configuration
/// </summary>
/// <value>The value pointing to the file system where the ssl certiifcate is located..</value>
public string CertificatePath { get; set; }
+ public string CertificatePassword { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is port authorized.
diff --git a/MediaBrowser.Model/Drawing/ImageSize.cs b/MediaBrowser.Model/Drawing/ImageSize.cs
index 8cf09da18..c2b0291bd 100644
--- a/MediaBrowser.Model/Drawing/ImageSize.cs
+++ b/MediaBrowser.Model/Drawing/ImageSize.cs
@@ -61,6 +61,12 @@ namespace MediaBrowser.Model.Drawing
_height = height;
}
+ public ImageSize(double width, double height)
+ {
+ _width = width;
+ _height = height;
+ }
+
private void ParseValue(string value)
{
if (!string.IsNullOrEmpty(value))
diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs
index 26de9332e..ea6b04824 100644
--- a/MediaBrowser.Model/IO/IFileSystem.cs
+++ b/MediaBrowser.Model/IO/IFileSystem.cs
@@ -108,6 +108,8 @@ namespace MediaBrowser.Model.IO
/// <returns>FileStream.</returns>
Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false);
+ Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, FileOpenOptions fileOpenOptions);
+
/// <summary>
/// Opens the read.
/// </summary>
@@ -311,7 +313,8 @@ namespace MediaBrowser.Model.IO
IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false);
void SetHidden(string path, bool isHidden);
- void SetReadOnly(string path, bool isHidden);
+ void SetReadOnly(string path, bool readOnly);
+ void SetAttributes(string path, bool isHidden, bool readOnly);
char DirectorySeparatorChar { get; }
@@ -402,4 +405,46 @@ namespace MediaBrowser.Model.IO
ReadWrite = 3
}
+ //
+ // Summary:
+ // Represents advanced options for creating a System.IO.FileStream object.
+ [Flags]
+ public enum FileOpenOptions
+ {
+ //
+ // Summary:
+ // Indicates that the system should write through any intermediate cache and go
+ // directly to disk.
+ WriteThrough = int.MinValue,
+ //
+ // Summary:
+ // Indicates that no additional options should be used when creating a System.IO.FileStream
+ // object.
+ None = 0,
+ //
+ // Summary:
+ // Indicates that a file is encrypted and can be decrypted only by using the same
+ // user account used for encryption.
+ Encrypted = 16384,
+ //
+ // Summary:
+ // Indicates that a file is automatically deleted when it is no longer in use.
+ DeleteOnClose = 67108864,
+ //
+ // Summary:
+ // Indicates that the file is to be accessed sequentially from beginning to end.
+ // The system can use this as a hint to optimize file caching. If an application
+ // moves the file pointer for random access, optimum caching may not occur; however,
+ // correct operation is still guaranteed.
+ SequentialScan = 134217728,
+ //
+ // Summary:
+ // Indicates that the file is accessed randomly. The system can use this as a hint
+ // to optimize file caching.
+ RandomAccess = 268435456,
+ //
+ // Summary:
+ // Indicates that a file can be used for asynchronous reading and writing.
+ Asynchronous = 1073741824
+ }
}
diff --git a/MediaBrowser.Model/Services/IRequest.cs b/MediaBrowser.Model/Services/IRequest.cs
index 115ba25ce..f056c7410 100644
--- a/MediaBrowser.Model/Services/IRequest.cs
+++ b/MediaBrowser.Model/Services/IRequest.cs
@@ -155,6 +155,8 @@ namespace MediaBrowser.Model.Services
//Add Metadata to Response
Dictionary<string, object> Items { get; }
+ QueryParamCollection Headers { get; }
+
Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs
index 1d8275c26..4bd504409 100644
--- a/MediaBrowser.Providers/Manager/ImageSaver.cs
+++ b/MediaBrowser.Providers/Manager/ImageSaver.cs
@@ -166,7 +166,7 @@ namespace MediaBrowser.Providers.Manager
{
var currentPath = currentImagePath;
- _logger.Debug("Deleting previous image {0}", currentPath);
+ _logger.Info("Deleting previous image {0}", currentPath);
_libraryMonitor.ReportFileSystemChangeBeginning(currentPath);
@@ -236,7 +236,7 @@ namespace MediaBrowser.Providers.Manager
/// <returns>Task.</returns>
private async Task SaveImageToLocation(Stream source, string path, CancellationToken cancellationToken)
{
- _logger.Debug("Saving image to {0}", path);
+ _logger.Info("Saving image to {0}", path);
var parentFolder = _fileSystem.GetDirectoryName(path);
@@ -249,31 +249,16 @@ namespace MediaBrowser.Providers.Manager
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(path));
- // If the file is currently hidden we'll have to remove that or the save will fail
- var file = _fileSystem.GetFileInfo(path);
+ _fileSystem.SetAttributes(path, false, false);
- // This will fail if the file is hidden
- if (file.Exists)
+ using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, FileOpenOptions.Asynchronous))
{
- if (file.IsHidden)
- {
- _fileSystem.SetHidden(file.FullName, false);
- }
- if (file.IsReadOnly)
- {
- _fileSystem.SetReadOnly(path, false);
- }
- }
-
- using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
- {
- await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken)
- .ConfigureAwait(false);
+ await source.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
}
if (_config.Configuration.SaveMetadataHidden)
{
- _fileSystem.SetHidden(file.FullName, true);
+ _fileSystem.SetHidden(path, true);
}
}
finally
diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs
index f544c09dc..d5494c21f 100644
--- a/MediaBrowser.Providers/Manager/ProviderUtils.cs
+++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs
@@ -200,6 +200,7 @@ namespace MediaBrowser.Providers.Manager
MergeCriticRating(source, target, lockedFields, replaceData);
MergeAwards(source, target, lockedFields, replaceData);
MergeTrailers(source, target, lockedFields, replaceData);
+ MergeVideoInfo(source, target, lockedFields, replaceData);
if (mergeMetadataSettings)
{
@@ -307,5 +308,19 @@ namespace MediaBrowser.Providers.Manager
}
}
}
+
+ private static void MergeVideoInfo(BaseItem source, BaseItem target, List<MetadataFields> lockedFields, bool replaceData)
+ {
+ var sourceCast = source as Video;
+ var targetCast = target as Video;
+
+ if (sourceCast != null && targetCast != null)
+ {
+ if (replaceData || targetCast.Video3DFormat == null)
+ {
+ targetCast.Video3DFormat = sourceCast.Video3DFormat;
+ }
+ }
+ }
}
}
diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
index 477543d5e..f9d19b6be 100644
--- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
@@ -72,8 +72,7 @@ namespace MediaBrowser.Providers.Omdb
var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb);
- var baseUrl = await OmdbProvider.GetOmdbBaseUrl(cancellationToken).ConfigureAwait(false);
- var url = baseUrl + "/?plot=full&r=json";
+ var urlQuery = "plot=full&r=json";
if (type == "episode" && episodeSearchInfo != null)
{
episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out imdbId);
@@ -94,23 +93,23 @@ namespace MediaBrowser.Providers.Omdb
{
if (year.HasValue)
{
- url += "&y=" + year.Value.ToString(CultureInfo.InvariantCulture);
+ urlQuery += "&y=" + year.Value.ToString(CultureInfo.InvariantCulture);
}
// &s means search and returns a list of results as opposed to t
if (isSearch)
{
- url += "&s=" + WebUtility.UrlEncode(name);
+ urlQuery += "&s=" + WebUtility.UrlEncode(name);
}
else
{
- url += "&t=" + WebUtility.UrlEncode(name);
+ urlQuery += "&t=" + WebUtility.UrlEncode(name);
}
- url += "&type=" + type;
+ urlQuery += "&type=" + type;
}
else
{
- url += "&i=" + imdbId;
+ urlQuery += "&i=" + imdbId;
isSearch = false;
}
@@ -118,14 +117,16 @@ namespace MediaBrowser.Providers.Omdb
{
if (searchInfo.IndexNumber.HasValue)
{
- url += string.Format(CultureInfo.InvariantCulture, "&Episode={0}", searchInfo.IndexNumber);
+ urlQuery += string.Format(CultureInfo.InvariantCulture, "&Episode={0}", searchInfo.IndexNumber);
}
if (searchInfo.ParentIndexNumber.HasValue)
{
- url += string.Format(CultureInfo.InvariantCulture, "&Season={0}", searchInfo.ParentIndexNumber);
+ urlQuery += string.Format(CultureInfo.InvariantCulture, "&Season={0}", searchInfo.ParentIndexNumber);
}
}
+ var url = await OmdbProvider.GetOmdbUrl(urlQuery, cancellationToken).ConfigureAwait(false);
+
using (var stream = await OmdbProvider.GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{
var resultList = new List<SearchResult>();
diff --git a/MediaBrowser.Providers/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Omdb/OmdbProvider.cs
index d1c3b2214..b89105376 100644
--- a/MediaBrowser.Providers/Omdb/OmdbProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbProvider.cs
@@ -265,9 +265,16 @@ namespace MediaBrowser.Providers.Omdb
return false;
}
- public static async Task<string> GetOmdbBaseUrl(CancellationToken cancellationToken)
+ public static async Task<string> GetOmdbUrl(string query, CancellationToken cancellationToken)
{
- return "https://www.omdbapi.com";
+ var url = "https://www.omdbapi.com?apikey=fe53f97e";
+
+ if (!string.IsNullOrWhiteSpace(query))
+ {
+ url += "&" + query;
+ }
+
+ return url;
}
private async Task<string> EnsureItemInfo(string imdbId, CancellationToken cancellationToken)
@@ -292,8 +299,7 @@ namespace MediaBrowser.Providers.Omdb
}
}
- var baseUrl = await GetOmdbBaseUrl(cancellationToken).ConfigureAwait(false);
- var url = string.Format(baseUrl + "/?i={0}&plot=full&tomatoes=true&r=json", imdbParam);
+ var url = await GetOmdbUrl(string.Format("i={0}&plot=full&tomatoes=true&r=json", imdbParam), cancellationToken).ConfigureAwait(false);
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{
@@ -327,8 +333,7 @@ namespace MediaBrowser.Providers.Omdb
}
}
- var baseUrl = await GetOmdbBaseUrl(cancellationToken).ConfigureAwait(false);
- var url = string.Format(baseUrl + "/?i={0}&season={1}&detail=full", imdbParam, seasonId);
+ var url = await GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), cancellationToken).ConfigureAwait(false);
using (var stream = await GetOmdbResponse(_httpClient, url, cancellationToken).ConfigureAwait(false))
{
diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
index 8133efafb..73626328a 100644
--- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
+++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
@@ -122,10 +122,10 @@
<HintPath>..\ThirdParty\taglib\TagLib.Portable.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.core">
- <HintPath>..\packages\SQLitePCLRaw.core.1.1.2\lib\net45\SQLitePCLRaw.core.dll</HintPath>
+ <HintPath>..\packages\SQLitePCLRaw.core.1.1.5\lib\net45\SQLitePCLRaw.core.dll</HintPath>
</Reference>
<Reference Include="SQLitePCLRaw.provider.sqlite3">
- <HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.2\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
+ <HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.5\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
</Reference>
<Reference Include="Emby.Server.Connect">
<HintPath>..\ThirdParty\emby\Emby.Server.Connect.dll</HintPath>
diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
index bcdfa858f..e4bde07c7 100644
--- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
+++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
@@ -94,11 +94,11 @@
<Private>True</Private>
</Reference>
<Reference Include="SQLitePCLRaw.core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1488e028ca7ab535, processorArchitecture=MSIL">
- <HintPath>..\packages\SQLitePCLRaw.core.1.1.2\lib\net45\SQLitePCLRaw.core.dll</HintPath>
+ <HintPath>..\packages\SQLitePCLRaw.core.1.1.5\lib\net45\SQLitePCLRaw.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLitePCLRaw.provider.sqlite3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=62684c7b4f184e3f, processorArchitecture=MSIL">
- <HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.2\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
+ <HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.5\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
diff --git a/MediaBrowser.Server.Mono/packages.config b/MediaBrowser.Server.Mono/packages.config
index 81da308f5..de26c7666 100644
--- a/MediaBrowser.Server.Mono/packages.config
+++ b/MediaBrowser.Server.Mono/packages.config
@@ -5,6 +5,6 @@
<package id="ServiceStack.Text" version="4.5.4" targetFramework="net46" />
<package id="SharpCompress" version="0.14.0" targetFramework="net46" />
<package id="SimpleInjector" version="3.3.2" targetFramework="net46" />
- <package id="SQLitePCLRaw.core" version="1.1.2" targetFramework="net46" />
- <package id="SQLitePCLRaw.provider.sqlite3.net45" version="1.1.2" targetFramework="net46" />
+ <package id="SQLitePCLRaw.core" version="1.1.5" targetFramework="net46" />
+ <package id="SQLitePCLRaw.provider.sqlite3.net45" version="1.1.5" targetFramework="net46" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.ServerApplication/ImageEncoderHelper.cs b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs
index ddbde2f66..b8fa097d6 100644
--- a/MediaBrowser.ServerApplication/ImageEncoderHelper.cs
+++ b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs
@@ -2,6 +2,7 @@
using Emby.Drawing;
using Emby.Drawing.Net;
using Emby.Drawing.ImageMagick;
+using Emby.Drawing.Skia;
using Emby.Server.Core;
using Emby.Server.Implementations;
using MediaBrowser.Common.Configuration;
@@ -25,6 +26,15 @@ namespace MediaBrowser.Server.Startup.Common
{
try
{
+ return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem);
+ }
+ catch
+ {
+ logger.Error("Error loading Skia. Will revert to ImageMagick.");
+ }
+
+ try
+ {
return new ImageMagickEncoder(logManager.GetLogger("ImageMagick"), appPaths, httpClient, fileSystem);
}
catch
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index 8e38c9a98..272054609 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -22,6 +22,7 @@ using Emby.Common.Implementations.IO;
using Emby.Common.Implementations.Logging;
using Emby.Common.Implementations.Networking;
using Emby.Common.Implementations.Security;
+using Emby.Drawing;
using Emby.Server.Core;
using Emby.Server.Core.Logging;
using Emby.Server.Implementations;
@@ -335,8 +336,6 @@ namespace MediaBrowser.ServerApplication
var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), environmentInfo, appPaths.TempDirectory);
- var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths);
-
FileSystem = fileSystem;
_appHost = new WindowsAppHost(appPaths,
@@ -346,7 +345,7 @@ namespace MediaBrowser.ServerApplication
new PowerManagement(),
"emby.windows.zip",
environmentInfo,
- imageEncoder,
+ new NullImageEncoder(),
new Server.Startup.Common.SystemEvents(logManager.GetLogger("SystemEvents")),
new RecyclableMemoryStreamProvider(),
new Networking.NetworkManager(logManager.GetLogger("NetworkManager")),
@@ -367,6 +366,19 @@ namespace MediaBrowser.ServerApplication
var task = _appHost.Init(initProgress);
Task.WaitAll(task);
+ if (!runService)
+ {
+ task = InstallVcredist2013IfNeeded(_appHost, _logger);
+ Task.WaitAll(task);
+
+ // needed by skia
+ task = InstallVcredist2015IfNeeded(_appHost, _logger);
+ Task.WaitAll(task);
+ }
+
+ // set image encoder here
+ _appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths);
+
task = task.ContinueWith(new Action<Task>(a => _appHost.RunStartupTasks()), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent);
if (runService)
@@ -377,9 +389,6 @@ namespace MediaBrowser.ServerApplication
{
Task.WaitAll(task);
- task = InstallVcredist2013IfNeeded(_appHost, _logger);
- Task.WaitAll(task);
-
Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
HideSplashScreen();
@@ -736,32 +745,61 @@ namespace MediaBrowser.ServerApplication
Process.Start(startInfo);
}
- private static bool CanRestartWindowsService()
+ private static async Task InstallVcredist2013IfNeeded(ApplicationHost appHost, ILogger logger)
{
- var startInfo = new ProcessStartInfo
- {
- FileName = "cmd.exe",
- CreateNoWindow = true,
- WindowStyle = ProcessWindowStyle.Hidden,
- Verb = "runas",
- ErrorDialog = false,
- Arguments = String.Format("/c sc query {0}", BackgroundService.GetExistingServiceName())
- };
- using (var process = Process.Start(startInfo))
+ // Reference
+ // http://stackoverflow.com/questions/12206314/detect-if-visual-c-redistributable-for-visual-studio-2012-is-installed
+
+ try
{
- process.WaitForExit();
- if (process.ExitCode == 0)
- {
- return true;
- }
- else
+ var subkey = Environment.Is64BitProcess
+ ? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x64"
+ : "SOFTWARE\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x86";
+
+ using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default)
+ .OpenSubKey(subkey))
{
- return false;
+ if (ndpKey != null && ndpKey.GetValue("Version") != null)
+ {
+ var installedVersion = ((string)ndpKey.GetValue("Version")).TrimStart('v');
+ if (installedVersion.StartsWith("12", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+ }
}
}
+ catch (Exception ex)
+ {
+ logger.ErrorException("Error getting .NET Framework version", ex);
+ return;
+ }
+
+ MessageBox.Show("The Visual C++ 2013 Runtime will now be installed.", "Install Visual C++ Runtime", MessageBoxButtons.OK, MessageBoxIcon.Information);
+
+ try
+ {
+ await InstallVcredist(GetVcredist2013Url()).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ logger.ErrorException("Error installing Visual Studio C++ runtime", ex);
+ }
}
- private static async Task InstallVcredist2013IfNeeded(ApplicationHost appHost, ILogger logger)
+ private static string GetVcredist2013Url()
+ {
+ if (Environment.Is64BitProcess)
+ {
+ return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x64.exe";
+ }
+
+ // TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_arm.exe
+
+ return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x86.exe";
+ }
+
+ private static async Task InstallVcredist2015IfNeeded(ApplicationHost appHost, ILogger logger)
{
// Reference
// http://stackoverflow.com/questions/12206314/detect-if-visual-c-redistributable-for-visual-studio-2012-is-installed
@@ -769,8 +807,8 @@ namespace MediaBrowser.ServerApplication
try
{
var subkey = Environment.Is64BitProcess
- ? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x64"
- : "SOFTWARE\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x86";
+ ? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64"
+ : "SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x86";
using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default)
.OpenSubKey(subkey))
@@ -778,7 +816,7 @@ namespace MediaBrowser.ServerApplication
if (ndpKey != null && ndpKey.GetValue("Version") != null)
{
var installedVersion = ((string)ndpKey.GetValue("Version")).TrimStart('v');
- if (installedVersion.StartsWith("12", StringComparison.OrdinalIgnoreCase))
+ if (installedVersion.StartsWith("14", StringComparison.OrdinalIgnoreCase))
{
return;
}
@@ -791,9 +829,11 @@ namespace MediaBrowser.ServerApplication
return;
}
+ MessageBox.Show("The Visual C++ 2015 Runtime will now be installed.", "Install Visual C++ Runtime", MessageBoxButtons.OK, MessageBoxIcon.Information);
+
try
{
- await InstallVcredist2013().ConfigureAwait(false);
+ await InstallVcredist(GetVcredist2015Url()).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -801,13 +841,25 @@ namespace MediaBrowser.ServerApplication
}
}
- private async static Task InstallVcredist2013()
+ private static string GetVcredist2015Url()
+ {
+ if (Environment.Is64BitProcess)
+ {
+ return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2015/vc_redist.x64.exe";
+ }
+
+ // TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2015/vcredist_arm.exe
+
+ return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2015/vc_redist.x86.exe";
+ }
+
+ private async static Task InstallVcredist(string url)
{
var httpClient = _appHost.HttpClient;
var tmp = await httpClient.GetTempFile(new HttpRequestOptions
{
- Url = GetVcredist2013Url(),
+ Url = url,
Progress = new Progress<double>()
}).ConfigureAwait(false);
@@ -833,18 +885,6 @@ namespace MediaBrowser.ServerApplication
}
}
- private static string GetVcredist2013Url()
- {
- if (Environment.Is64BitProcess)
- {
- return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x64.exe";
- }
-
- // TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_arm.exe
-
- return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x86.exe";
- }
-
/// <summary>
/// Sets the error mode.
/// </summary>
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index 749468fe2..d632007d2 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -99,12 +99,16 @@
<HintPath>..\packages\SimpleInjector.3.3.2\lib\net45\SimpleInjector.dll</HintPath>
<Private>True</Private>
</Reference>
+ <Reference Include="SkiaSharp, Version=1.57.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+ <HintPath>..\packages\SkiaSharp.1.57.1\lib\net45\SkiaSharp.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
<Reference Include="SQLitePCLRaw.core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1488e028ca7ab535, processorArchitecture=MSIL">
- <HintPath>..\packages\SQLitePCLRaw.core.1.1.2\lib\net45\SQLitePCLRaw.core.dll</HintPath>
+ <HintPath>..\packages\SQLitePCLRaw.core.1.1.5\lib\net45\SQLitePCLRaw.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SQLitePCLRaw.provider.sqlite3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=62684c7b4f184e3f, processorArchitecture=MSIL">
- <HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.2\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
+ <HintPath>..\packages\SQLitePCLRaw.provider.sqlite3.net45.1.1.5\lib\net45\SQLitePCLRaw.provider.sqlite3.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
@@ -185,6 +189,14 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
+ <Content Include="..\packages\SkiaSharp.1.57.1\runtimes\win7-x64\native\libSkiaSharp.dll">
+ <Link>x64\libSkiaSharp.dll</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="..\packages\SkiaSharp.1.57.1\runtimes\win7-x86\native\libSkiaSharp.dll">
+ <Link>x86\libSkiaSharp.dll</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="..\Tools\Installation\MediaBrowser.InstallUtil.dll">
<Link>MediaBrowser.InstallUtil.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -1100,6 +1112,10 @@
<Project>{c97a239e-a96c-4d64-a844-ccf8cc30aecb}</Project>
<Name>Emby.Drawing.Net</Name>
</ProjectReference>
+ <ProjectReference Include="..\Emby.Drawing.Skia\Emby.Drawing.Skia.csproj">
+ <Project>{2312da6d-ff86-4597-9777-bceec32d96dd}</Project>
+ <Name>Emby.Drawing.Skia</Name>
+ </ProjectReference>
<ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj">
<Project>{08fff49b-f175-4807-a2b5-73b0ebd9f716}</Project>
<Name>Emby.Drawing</Name>
diff --git a/MediaBrowser.ServerApplication/Native/LoopUtil.cs b/MediaBrowser.ServerApplication/Native/LoopUtil.cs
index 9a96f5518..7c7471231 100644
--- a/MediaBrowser.ServerApplication/Native/LoopUtil.cs
+++ b/MediaBrowser.ServerApplication/Native/LoopUtil.cs
@@ -57,10 +57,6 @@ namespace MediaBrowser.ServerApplication.Native
}
- // Call this API to free the memory returned by the Enumeration API
- [DllImport("FirewallAPI.dll")]
- internal static extern void NetworkIsolationFreeAppContainers(IntPtr pACs);
-
// Call this API to load the current list of LoopUtil-enabled AppContainers
[DllImport("FirewallAPI.dll")]
internal static extern uint NetworkIsolationGetAppContainerConfig(out uint pdwCntACs, out IntPtr appContainerSids);
@@ -69,23 +65,13 @@ namespace MediaBrowser.ServerApplication.Native
[DllImport("FirewallAPI.dll")]
private static extern uint NetworkIsolationSetAppContainerConfig(uint pdwCntACs, SID_AND_ATTRIBUTES[] appContainerSids);
-
// Use this API to convert a string SID into an actual SID
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool ConvertStringSidToSid(string strSid, out IntPtr pSid);
[DllImport("advapi32", /*CharSet = CharSet.Auto,*/ SetLastError = true)]
- static extern bool ConvertSidToStringSid(
- [MarshalAs(UnmanagedType.LPArray)] byte[] pSID,
- out IntPtr ptrSid);
-
- [DllImport("advapi32", /*CharSet = CharSet.Auto,*/ SetLastError = true)]
static extern bool ConvertSidToStringSid(IntPtr pSid, out string strSid);
- // Use this API to convert a string reference (e.g. "@{blah.pri?ms-resource://whatever}") into a plain string
- [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf);
-
// Call this API to enumerate all of the AppContainers on the system
[DllImport("FirewallAPI.dll")]
internal static extern uint NetworkIsolationEnumAppContainers(uint Flags, out uint pdwCntPublicACs, out IntPtr ppACs);
@@ -196,7 +182,6 @@ namespace MediaBrowser.ServerApplication.Native
{
util.SaveLoopbackState();
}
- util.SaveLoopbackState();
}
private static List<SID_AND_ATTRIBUTES> PI_NetworkIsolationGetAppContainerConfig()
@@ -305,11 +290,5 @@ namespace MediaBrowser.ServerApplication.Native
}
return count;
}
-
- public void FreeResources()
- {
- NetworkIsolationFreeAppContainers(_pACs);
- }
-
}
}
diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config
index 68d0a7fda..2d4ba6170 100644
--- a/MediaBrowser.ServerApplication/packages.config
+++ b/MediaBrowser.ServerApplication/packages.config
@@ -5,6 +5,7 @@
<package id="ServiceStack.Text" version="4.5.4" targetFramework="net462" />
<package id="SharpCompress" version="0.14.0" targetFramework="net462" />
<package id="SimpleInjector" version="3.3.2" targetFramework="net462" />
- <package id="SQLitePCLRaw.core" version="1.1.2" targetFramework="net462" />
- <package id="SQLitePCLRaw.provider.sqlite3.net45" version="1.1.2" targetFramework="net462" />
+ <package id="SkiaSharp" version="1.57.1" targetFramework="net462" />
+ <package id="SQLitePCLRaw.core" version="1.1.5" targetFramework="net462" />
+ <package id="SQLitePCLRaw.provider.sqlite3.net45" version="1.1.5" targetFramework="net462" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
index dfd4694c3..d8f7cb57f 100644
--- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
+++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
@@ -15,6 +15,7 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Xml;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Xml;
@@ -227,6 +228,11 @@ namespace MediaBrowser.XbmcMetadata.Parsers
}
}
+ protected virtual string MovieDbParserSearchString
+ {
+ get { return "themoviedb.org/movie/"; }
+ }
+
private void ParseProviderLinks(T item, string xml)
{
//Look for a match for the Regex pattern "tt" followed by 7 digits
@@ -238,7 +244,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
// Support Tmdb
// http://www.themoviedb.org/movie/36557
- var srch = "themoviedb.org/movie/";
+ var srch = MovieDbParserSearchString;
var index = xml.IndexOf(srch, StringComparison.OrdinalIgnoreCase);
if (index != -1)
@@ -250,6 +256,23 @@ namespace MediaBrowser.XbmcMetadata.Parsers
item.SetProviderId(MetadataProviders.Tmdb, tmdbId);
}
}
+
+ if (item is Series)
+ {
+ srch = "thetvdb.com/?tab=series&id=";
+
+ index = xml.IndexOf(srch, StringComparison.OrdinalIgnoreCase);
+
+ if (index != -1)
+ {
+ var tvdbId = xml.Substring(index + srch.Length).TrimEnd('/');
+ int value;
+ if (!string.IsNullOrWhiteSpace(tvdbId) && int.TryParse(tvdbId, NumberStyles.Any, CultureInfo.InvariantCulture, out value))
+ {
+ item.SetProviderId(MetadataProviders.Tvdb, tvdbId);
+ }
+ }
+ }
}
protected virtual void FetchDataFromXmlNode(XmlReader reader, MetadataResult<T> itemResult)
diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs
index 98016f4f7..b0db4e6f3 100644
--- a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs
+++ b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs
@@ -13,6 +13,19 @@ namespace MediaBrowser.XbmcMetadata.Parsers
{
public class SeriesNfoParser : BaseNfoParser<Series>
{
+ protected override bool SupportsUrlAfterClosingXmlTag
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ protected override string MovieDbParserSearchString
+ {
+ get { return "themoviedb.org/tv/"; }
+ }
+
/// <summary>
/// Fetches the data from XML node.
/// </summary>
diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
index 623b109f7..ae2492802 100644
--- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
@@ -220,14 +220,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
{
if (file.IsHidden)
{
- FileSystem.SetHidden(path, false);
-
wasHidden = true;
}
- if (file.IsReadOnly)
- {
- FileSystem.SetReadOnly(path, false);
- }
+ FileSystem.SetAttributes(path, false, false);
}
using (var filestream = FileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index b9933969f..219beeab1 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -80,6 +80,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing.Net", "Emby.Dr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SocketHttpListener.Portable", "SocketHttpListener.Portable\SocketHttpListener.Portable.csproj", "{4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing.Skia", "Emby.Drawing.Skia\Emby.Drawing.Skia.csproj", "{2312DA6D-FF86-4597-9777-BCEEC32D96DD}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1099,6 +1101,46 @@ Global
{4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Signed|x64.Build.0 = Release|Any CPU
{4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Signed|x86.ActiveCfg = Release|Any CPU
{4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Signed|x86.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Win32.Build.0 = Debug|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|x64.Build.0 = Debug|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|x86.Build.0 = Debug|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release Mono|Any CPU.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release Mono|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release Mono|Mixed Platforms.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release Mono|Win32.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release Mono|Win32.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release Mono|x64.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release Mono|x64.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release Mono|x86.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release Mono|x86.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Win32.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Win32.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|x64.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|x64.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|x86.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|x86.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|Any CPU.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|Any CPU.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|Mixed Platforms.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|Win32.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|Win32.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x64.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x64.Build.0 = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x86.ActiveCfg = Release|Any CPU
+ {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index c86e9a71c..64e4d1418 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.699</version>
+ <version>3.0.700</version>
<title>Emby.Common</title>
<authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index f68cf4e41..917288cb1 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.699</version>
+ <version>3.0.700</version>
<title>Emby.Server.Core</title>
<authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Emby Server.</description>
<copyright>Copyright © Emby 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.699" />
+ <dependency id="MediaBrowser.Common" version="3.0.700" />
</dependencies>
</metadata>
<files>
diff --git a/SocketHttpListener.Portable/Net/EndPointListener.cs b/SocketHttpListener.Portable/Net/EndPointListener.cs
index 4f1a17fc0..2106bbec5 100644
--- a/SocketHttpListener.Portable/Net/EndPointListener.cs
+++ b/SocketHttpListener.Portable/Net/EndPointListener.cs
@@ -8,6 +8,7 @@ using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
+using MediaBrowser.Model.System;
using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives;
@@ -33,8 +34,9 @@ namespace SocketHttpListener.Net
private readonly ITextEncoding _textEncoding;
private readonly IMemoryStreamFactory _memoryStreamFactory;
private readonly IFileSystem _fileSystem;
+ private readonly IEnvironmentInfo _environment;
- public EndPointListener(HttpListener listener, IpAddressInfo addr, int port, bool secure, ICertificate cert, ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem)
+ public EndPointListener(HttpListener listener, IpAddressInfo addr, int port, bool secure, ICertificate cert, ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IEnvironmentInfo environment)
{
this.listener = listener;
_logger = logger;
@@ -44,6 +46,7 @@ namespace SocketHttpListener.Net
_memoryStreamFactory = memoryStreamFactory;
_textEncoding = textEncoding;
_fileSystem = fileSystem;
+ _environment = environment;
this.secure = secure;
this.cert = cert;
@@ -109,7 +112,7 @@ namespace SocketHttpListener.Net
return;
}
- HttpConnection conn = await HttpConnection.Create(_logger, accepted, listener, listener.secure, listener.cert, _cryptoProvider, _streamFactory, _memoryStreamFactory, _textEncoding, _fileSystem).ConfigureAwait(false);
+ HttpConnection conn = await HttpConnection.Create(_logger, accepted, listener, listener.secure, listener.cert, _cryptoProvider, _streamFactory, _memoryStreamFactory, _textEncoding, _fileSystem, _environment).ConfigureAwait(false);
//_logger.Debug("Adding unregistered connection to {0}. Id: {1}", accepted.RemoteEndPoint, connectionId);
lock (listener.unregistered)
diff --git a/SocketHttpListener.Portable/Net/EndPointManager.cs b/SocketHttpListener.Portable/Net/EndPointManager.cs
index 11f774915..6a00ed360 100644
--- a/SocketHttpListener.Portable/Net/EndPointManager.cs
+++ b/SocketHttpListener.Portable/Net/EndPointManager.cs
@@ -106,7 +106,7 @@ namespace SocketHttpListener.Net
}
else
{
- epl = new EndPointListener(listener, addr, port, secure, listener.Certificate, logger, listener.CryptoProvider, listener.StreamFactory, listener.SocketFactory, listener.MemoryStreamFactory, listener.TextEncoding, listener.FileSystem);
+ epl = new EndPointListener(listener, addr, port, secure, listener.Certificate, logger, listener.CryptoProvider, listener.StreamFactory, listener.SocketFactory, listener.MemoryStreamFactory, listener.TextEncoding, listener.FileSystem, listener.EnvironmentInfo);
p[port] = epl;
}
diff --git a/SocketHttpListener.Portable/Net/HttpConnection.cs b/SocketHttpListener.Portable/Net/HttpConnection.cs
index ac8ada486..65e7470f7 100644
--- a/SocketHttpListener.Portable/Net/HttpConnection.cs
+++ b/SocketHttpListener.Portable/Net/HttpConnection.cs
@@ -6,6 +6,7 @@ using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
+using MediaBrowser.Model.System;
using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives;
@@ -41,8 +42,9 @@ namespace SocketHttpListener.Net
private readonly ITextEncoding _textEncoding;
private readonly IStreamFactory _streamFactory;
private readonly IFileSystem _fileSystem;
+ private readonly IEnvironmentInfo _environment;
- private HttpConnection(ILogger logger, IAcceptSocket sock, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem)
+ private HttpConnection(ILogger logger, IAcceptSocket sock, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IEnvironmentInfo environment)
{
_logger = logger;
this.sock = sock;
@@ -53,6 +55,7 @@ namespace SocketHttpListener.Net
_memoryStreamFactory = memoryStreamFactory;
_textEncoding = textEncoding;
_fileSystem = fileSystem;
+ _environment = environment;
_streamFactory = streamFactory;
}
@@ -84,9 +87,9 @@ namespace SocketHttpListener.Net
Init();
}
- public static async Task<HttpConnection> Create(ILogger logger, IAcceptSocket sock, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem)
+ public static async Task<HttpConnection> Create(ILogger logger, IAcceptSocket sock, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IEnvironmentInfo environment)
{
- var connection = new HttpConnection(logger, sock, epl, secure, cert, cryptoProvider, streamFactory, memoryStreamFactory, textEncoding, fileSystem);
+ var connection = new HttpConnection(logger, sock, epl, secure, cert, cryptoProvider, streamFactory, memoryStreamFactory, textEncoding, fileSystem, environment);
await connection.InitStream().ConfigureAwait(false);
@@ -217,7 +220,7 @@ namespace SocketHttpListener.Net
{
var supportsDirectSocketAccess = !context.Response.SendChunked && !isExpect100Continue && !secure;
- o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding, _fileSystem, sock, supportsDirectSocketAccess, _logger);
+ o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding, _fileSystem, sock, supportsDirectSocketAccess, _logger, _environment);
}
else
{
diff --git a/SocketHttpListener.Portable/Net/HttpListener.cs b/SocketHttpListener.Portable/Net/HttpListener.cs
index c2e7acd8e..b3e01425c 100644
--- a/SocketHttpListener.Portable/Net/HttpListener.cs
+++ b/SocketHttpListener.Portable/Net/HttpListener.cs
@@ -8,6 +8,7 @@ using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
+using MediaBrowser.Model.System;
using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives;
@@ -22,6 +23,7 @@ namespace SocketHttpListener.Net
internal ITextEncoding TextEncoding { get; private set; }
internal IMemoryStreamFactory MemoryStreamFactory { get; private set; }
internal INetworkManager NetworkManager { get; private set; }
+ internal IEnvironmentInfo EnvironmentInfo { get; private set; }
public bool EnableDualMode { get; set; }
@@ -40,7 +42,7 @@ namespace SocketHttpListener.Net
public Action<HttpListenerContext> OnContext { get; set; }
- public HttpListener(ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem)
+ public HttpListener(ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo)
{
_logger = logger;
CryptoProvider = cryptoProvider;
@@ -50,19 +52,20 @@ namespace SocketHttpListener.Net
TextEncoding = textEncoding;
MemoryStreamFactory = memoryStreamFactory;
FileSystem = fileSystem;
+ EnvironmentInfo = environmentInfo;
prefixes = new HttpListenerPrefixCollection(logger, this);
registry = new Dictionary<HttpListenerContext, HttpListenerContext>();
connections = new Dictionary<HttpConnection, HttpConnection>();
auth_schemes = AuthenticationSchemes.Anonymous;
}
- public HttpListener(ICertificate certificate, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem)
- :this(new NullLogger(), certificate, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem)
+ public HttpListener(ICertificate certificate, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo)
+ :this(new NullLogger(), certificate, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem, environmentInfo)
{
}
- public HttpListener(ILogger logger, ICertificate certificate, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem)
- : this(logger, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem)
+ public HttpListener(ILogger logger, ICertificate certificate, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo)
+ : this(logger, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem, environmentInfo)
{
_certificate = certificate;
}
diff --git a/SocketHttpListener.Portable/Net/ResponseStream.cs b/SocketHttpListener.Portable/Net/ResponseStream.cs
index dea4049d5..9552fe8ca 100644
--- a/SocketHttpListener.Portable/Net/ResponseStream.cs
+++ b/SocketHttpListener.Portable/Net/ResponseStream.cs
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
+using MediaBrowser.Model.System;
using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives;
@@ -28,8 +29,9 @@ namespace SocketHttpListener.Net
private readonly IAcceptSocket _socket;
private readonly bool _supportsDirectSocketAccess;
private readonly ILogger _logger;
+ private readonly IEnvironmentInfo _environment;
- internal ResponseStream(Stream stream, HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IAcceptSocket socket, bool supportsDirectSocketAccess, ILogger logger)
+ internal ResponseStream(Stream stream, HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IAcceptSocket socket, bool supportsDirectSocketAccess, ILogger logger, IEnvironmentInfo environment)
{
this.response = response;
_memoryStreamFactory = memoryStreamFactory;
@@ -38,6 +40,7 @@ namespace SocketHttpListener.Net
_socket = socket;
_supportsDirectSocketAccess = supportsDirectSocketAccess;
_logger = logger;
+ _environment = environment;
this.stream = stream;
}
@@ -344,7 +347,20 @@ namespace SocketHttpListener.Net
private async Task TransmitFileManaged(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
{
- using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, fileShareMode, true))
+ var allowAsync = _environment.OperatingSystem != OperatingSystem.Windows;
+
+ var fileOpenOptions = offset > 0
+ ? FileOpenOptions.RandomAccess
+ : FileOpenOptions.SequentialScan;
+
+ if (allowAsync)
+ {
+ fileOpenOptions |= FileOpenOptions.Asynchronous;
+ }
+
+ // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
+
+ using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, fileShareMode, fileOpenOptions))
{
if (offset > 0)
{
@@ -355,11 +371,53 @@ namespace SocketHttpListener.Net
if (count > 0)
{
- await CopyToInternalAsync(fs, targetStream, count, cancellationToken).ConfigureAwait(false);
+ if (allowAsync)
+ {
+ await CopyToInternalAsync(fs, targetStream, count, cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ await CopyToInternalAsyncWithSyncRead(fs, targetStream, count, cancellationToken).ConfigureAwait(false);
+ }
}
else
{
- await fs.CopyToAsync(targetStream, 81920, cancellationToken).ConfigureAwait(false);
+ if (allowAsync)
+ {
+ await fs.CopyToAsync(targetStream, 81920, cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ fs.CopyTo(targetStream, 81920);
+ }
+ }
+ }
+ }
+
+ private static async Task CopyToInternalAsyncWithSyncRead(Stream source, Stream destination, long copyLength, CancellationToken cancellationToken)
+ {
+ var array = new byte[81920];
+ int bytesRead;
+
+ while ((bytesRead = source.Read(array, 0, array.Length)) != 0)
+ {
+ if (bytesRead == 0)
+ {
+ break;
+ }
+
+ var bytesToWrite = Math.Min(bytesRead, copyLength);
+
+ if (bytesToWrite > 0)
+ {
+ await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToWrite), cancellationToken).ConfigureAwait(false);
+ }
+
+ copyLength -= bytesToWrite;
+
+ if (copyLength <= 0)
+ {
+ break;
}
}
}
@@ -368,7 +426,7 @@ namespace SocketHttpListener.Net
{
var array = new byte[81920];
int bytesRead;
-
+
while ((bytesRead = await source.ReadAsync(array, 0, array.Length, cancellationToken).ConfigureAwait(false)) != 0)
{
if (bytesRead == 0)