aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Dlna/DlnaManager.cs1
-rw-r--r--Emby.Dlna/Emby.Dlna.csproj2
-rw-r--r--Emby.Dlna/Profiles/DefaultProfile.cs6
-rw-r--r--Emby.Dlna/Profiles/Xbox360Profile.cs326
-rw-r--r--Emby.Dlna/Profiles/XboxOneProfile.cs4
-rw-r--r--Emby.Dlna/Profiles/Xml/Default.xml4
-rw-r--r--Emby.Dlna/Profiles/Xml/Xbox 360.xml116
-rw-r--r--Emby.Dlna/Profiles/Xml/Xbox One.xml4
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs2
-rw-r--r--Emby.Server.Implementations/Channels/ChannelManager.cs16
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs2
-rw-r--r--Emby.Server.Implementations/IO/SharpCifsFileSystem.cs42
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs22
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs5
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs5
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs11
-rw-r--r--Emby.Server.Implementations/Localization/Core/bg-BG.json46
-rw-r--r--Emby.Server.Implementations/Localization/Core/sk.json36
-rw-r--r--Emby.Server.Implementations/Localization/Core/sv.json2
-rw-r--r--Emby.Server.Implementations/Localization/LocalizationManager.cs28
-rw-r--r--Emby.Server.Implementations/MediaEncoder/EncodingManager.cs9
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Audio/Audio.cs5
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs2
-rw-r--r--MediaBrowser.Controller/Entities/IHasMediaSources.cs1
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs5
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvChannel.cs5
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs16
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs3
-rw-r--r--MediaBrowser.Controller/Providers/DirectoryService.cs52
-rw-r--r--MediaBrowser.Controller/Providers/IDirectoryService.cs3
-rw-r--r--MediaBrowser.Model/Dto/BaseItemDto.cs3
-rw-r--r--MediaBrowser.Model/Providers/SubtitleOptions.cs2
-rw-r--r--MediaBrowser.Model/Session/GeneralCommandType.cs3
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs6
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs6
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs115
-rw-r--r--MediaBrowser.Providers/Subtitles/SubtitleManager.cs97
-rw-r--r--SharedVersion.cs2
41 files changed, 353 insertions, 673 deletions
diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs
index bdc523c8b..8caa086ee 100644
--- a/Emby.Dlna/DlnaManager.cs
+++ b/Emby.Dlna/DlnaManager.cs
@@ -554,7 +554,6 @@ namespace Emby.Dlna
var list = new List<DeviceProfile>
{
new SamsungSmartTvProfile(),
- new Xbox360Profile(),
new XboxOneProfile(),
new SonyPs3Profile(),
new SonyPs4Profile(),
diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj
index 365774b0d..eb8b178a8 100644
--- a/Emby.Dlna/Emby.Dlna.csproj
+++ b/Emby.Dlna/Emby.Dlna.csproj
@@ -105,7 +105,6 @@
<Compile Include="Profiles\SonyPs3Profile.cs" />
<Compile Include="Profiles\SonyPs4Profile.cs" />
<Compile Include="Profiles\WdtvLiveProfile.cs" />
- <Compile Include="Profiles\Xbox360Profile.cs" />
<Compile Include="Profiles\XboxOneProfile.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Server\DescriptionXmlBuilder.cs" />
@@ -175,7 +174,6 @@
<EmbeddedResource Include="Profiles\Xml\Sony PlayStation 3.xml" />
<EmbeddedResource Include="Profiles\Xml\Sony PlayStation 4.xml" />
<EmbeddedResource Include="Profiles\Xml\WDTV Live.xml" />
- <EmbeddedResource Include="Profiles\Xml\Xbox 360.xml" />
<EmbeddedResource Include="Profiles\Xml\Xbox One.xml" />
</ItemGroup>
<ItemGroup>
diff --git a/Emby.Dlna/Profiles/DefaultProfile.cs b/Emby.Dlna/Profiles/DefaultProfile.cs
index 46639ee42..75204b234 100644
--- a/Emby.Dlna/Profiles/DefaultProfile.cs
+++ b/Emby.Dlna/Profiles/DefaultProfile.cs
@@ -65,13 +65,15 @@ namespace Emby.Dlna.Profiles
{
new DirectPlayProfile
{
- Container = "m4v,mpegts,ts,3gp,mov,xvid,vob,mkv,wmv,asf,ogm,ogv,m2v,avi,mpg,mpeg,mp4,webm,wtv,m2ts,dvr-ms",
+ // play all
+ Container = "",
Type = DlnaProfileType.Video
},
new DirectPlayProfile
{
- Container = "aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac,m4a",
+ // play all
+ Container = "",
Type = DlnaProfileType.Audio
}
};
diff --git a/Emby.Dlna/Profiles/Xbox360Profile.cs b/Emby.Dlna/Profiles/Xbox360Profile.cs
deleted file mode 100644
index 7bdcd2a6f..000000000
--- a/Emby.Dlna/Profiles/Xbox360Profile.cs
+++ /dev/null
@@ -1,326 +0,0 @@
-using MediaBrowser.Model.Dlna;
-using System.Xml.Serialization;
-
-namespace Emby.Dlna.Profiles
-{
- /// <summary>
- /// Good info on xbox 360 requirements: https://code.google.com/p/jems/wiki/XBox360Notes
- /// </summary>
- [XmlRoot("Profile")]
- public class Xbox360Profile : DefaultProfile
- {
- public Xbox360Profile()
- {
- Name = "Xbox 360";
-
- // Required according to above
- ModelName = "Windows Media Player Sharing";
-
- ModelNumber = "12.0";
-
- FriendlyName = "${HostName}: 1";
-
- ModelUrl = "http://go.microsoft.com/fwlink/?LinkId=105926";
- Manufacturer = "Microsoft Corporation";
- ManufacturerUrl = "http://www.microsoft.com";
- XDlnaDoc = "DMS-1.50";
- ModelDescription = "Emby : UPnP Media Server";
-
- TimelineOffsetSeconds = 40;
- RequiresPlainFolders = true;
- RequiresPlainVideoItems = true;
- EnableMSMediaReceiverRegistrar = true;
-
- Identification = new DeviceIdentification
- {
- ModelName = "Xbox 360",
-
- Headers = new[]
- {
- new HttpHeaderInfo {Name = "User-Agent", Value = "Xbox", Match = HeaderMatchType.Substring},
- new HttpHeaderInfo {Name = "User-Agent", Value = "Xenon", Match = HeaderMatchType.Substring}
- }
- };
-
- TranscodingProfiles = new[]
- {
- new TranscodingProfile
- {
- Container = "mp3",
- AudioCodec = "mp3",
- Type = DlnaProfileType.Audio
- },
- new TranscodingProfile
- {
- Container = "asf",
- VideoCodec = "wmv2",
- AudioCodec = "wmav2",
- Type = DlnaProfileType.Video,
- TranscodeSeekInfo = TranscodeSeekInfo.Bytes,
- EstimateContentLength = true
- },
- new TranscodingProfile
- {
- Container = "jpeg",
- Type = DlnaProfileType.Photo
- }
- };
-
- DirectPlayProfiles = new[]
- {
- new DirectPlayProfile
- {
- Container = "avi",
- VideoCodec = "mpeg4",
- AudioCodec = "ac3,mp3",
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Container = "avi",
- VideoCodec = "h264",
- AudioCodec = "aac",
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Container = "mp4,mov",
- VideoCodec = "h264,mpeg4",
- AudioCodec = "aac,ac3",
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Container = "asf",
- VideoCodec = "wmv2,wmv3,vc1",
- AudioCodec = "wmav2,wmapro",
- Type = DlnaProfileType.Video
- },
- new DirectPlayProfile
- {
- Container = "asf",
- AudioCodec = "wmav2,wmapro,wmavoice",
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Container = "mp3",
- AudioCodec = "mp3",
- Type = DlnaProfileType.Audio
- },
- new DirectPlayProfile
- {
- Container = "jpeg",
- Type = DlnaProfileType.Photo
- }
- };
-
- ResponseProfiles = new[]
- {
- new ResponseProfile
- {
- Container = "avi",
- MimeType = "video/avi",
- Type = DlnaProfileType.Video
- }
- };
-
- ContainerProfiles = new[]
- {
- new ContainerProfile
- {
- Type = DlnaProfileType.Video,
- Container = "mp4,mov",
-
- Conditions = new []
- {
- new ProfileCondition
- {
- Condition = ProfileConditionType.Equals,
- Property = ProfileConditionValue.Has64BitOffsets,
- Value = "false",
- IsRequired = false
- }
- }
- },
-
- new ContainerProfile
- {
- Type = DlnaProfileType.Photo,
-
- Conditions = new []
- {
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.Width,
- Value = "1920"
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.Height,
- Value = "1080"
- }
- }
- }
- };
-
- CodecProfiles = new[]
- {
- new CodecProfile
- {
- Type = CodecType.Video,
- Codec = "mpeg4",
- Conditions = new []
- {
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.Width,
- Value = "1280"
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.Height,
- Value = "720"
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.VideoFramerate,
- Value = "30",
- IsRequired = false
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.VideoBitrate,
- Value = "5120000",
- IsRequired = false
- }
- }
- },
-
- new CodecProfile
- {
- Type = CodecType.Video,
- Codec = "h264",
- Conditions = new []
- {
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.Width,
- Value = "1920"
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.Height,
- Value = "1080"
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.VideoLevel,
- Value = "41",
- IsRequired = false
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.VideoBitrate,
- Value = "10240000",
- IsRequired = false
- }
- }
- },
-
- new CodecProfile
- {
- Type = CodecType.Video,
- Codec = "wmv2,wmv3,vc1",
- Conditions = new []
- {
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.Width,
- Value = "1920"
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.Height,
- Value = "1080"
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.VideoFramerate,
- Value = "30",
- IsRequired = false
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.VideoBitrate,
- Value = "15360000",
- IsRequired = false
- }
- }
- },
-
- new CodecProfile
- {
- Type = CodecType.VideoAudio,
- Codec = "ac3,wmav2,wmapro",
- Conditions = new []
- {
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.AudioChannels,
- Value = "6",
- IsRequired = false
- }
- }
- },
-
- new CodecProfile
- {
- Type = CodecType.VideoAudio,
- Codec = "aac",
- Conditions = new []
- {
- new ProfileCondition
- {
- Condition = ProfileConditionType.LessThanEqual,
- Property = ProfileConditionValue.AudioChannels,
- Value = "2",
- IsRequired = false
- },
- new ProfileCondition
- {
- Condition = ProfileConditionType.Equals,
- Property = ProfileConditionValue.AudioProfile,
- Value = "lc",
- IsRequired = false
- }
- }
- }
- };
-
- SubtitleProfiles = new[]
- {
- new SubtitleProfile
- {
- Format = "srt",
- Method = SubtitleDeliveryMethod.Embed
- }
- };
- }
- }
-}
diff --git a/Emby.Dlna/Profiles/XboxOneProfile.cs b/Emby.Dlna/Profiles/XboxOneProfile.cs
index e17640f2f..99e52510f 100644
--- a/Emby.Dlna/Profiles/XboxOneProfile.cs
+++ b/Emby.Dlna/Profiles/XboxOneProfile.cs
@@ -60,7 +60,7 @@ namespace Emby.Dlna.Profiles
new DirectPlayProfile
{
Container = "ts",
- VideoCodec = "h264,mpeg2video",
+ VideoCodec = "h264,mpeg2video,hevc",
AudioCodec = "ac3,aac,mp3",
Type = DlnaProfileType.Video
},
@@ -81,7 +81,7 @@ namespace Emby.Dlna.Profiles
new DirectPlayProfile
{
Container = "mp4,mov,mkv,m4v",
- VideoCodec = "h264,mpeg4,mpeg2video",
+ VideoCodec = "h264,mpeg4,mpeg2video,hevc",
AudioCodec = "aac,ac3",
Type = DlnaProfileType.Video
},
diff --git a/Emby.Dlna/Profiles/Xml/Default.xml b/Emby.Dlna/Profiles/Xml/Default.xml
index b07a2f7c2..133f4abf1 100644
--- a/Emby.Dlna/Profiles/Xml/Default.xml
+++ b/Emby.Dlna/Profiles/Xml/Default.xml
@@ -29,8 +29,8 @@
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<XmlRootAttributes />
<DirectPlayProfiles>
- <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,m4a" type="Audio" />
+ <DirectPlayProfile container="" type="Video" />
+ <DirectPlayProfile container="" 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" />
diff --git a/Emby.Dlna/Profiles/Xml/Xbox 360.xml b/Emby.Dlna/Profiles/Xml/Xbox 360.xml
deleted file mode 100644
index 3b7d2963f..000000000
--- a/Emby.Dlna/Profiles/Xml/Xbox 360.xml
+++ /dev/null
@@ -1,116 +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>Xbox 360</Name>
- <Identification>
- <ModelName>Xbox 360</ModelName>
- <Headers>
- <HttpHeaderInfo name="User-Agent" value="Xbox" match="Substring" />
- <HttpHeaderInfo name="User-Agent" value="Xenon" match="Substring" />
- </Headers>
- </Identification>
- <FriendlyName>${HostName}: 1</FriendlyName>
- <Manufacturer>Microsoft Corporation</Manufacturer>
- <ManufacturerUrl>http://www.microsoft.com</ManufacturerUrl>
- <ModelName>Windows Media Player Sharing</ModelName>
- <ModelDescription>Emby : UPnP Media Server</ModelDescription>
- <ModelNumber>12.0</ModelNumber>
- <ModelUrl>http://go.microsoft.com/fwlink/?LinkId=105926</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>40000000</MaxStreamingBitrate>
- <MaxStaticBitrate>40000000</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>40</TimelineOffsetSeconds>
- <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
- <RequiresPlainFolders>true</RequiresPlainFolders>
- <EnableMSMediaReceiverRegistrar>true</EnableMSMediaReceiverRegistrar>
- <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
- <XmlRootAttributes />
- <DirectPlayProfiles>
- <DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
- <DirectPlayProfile container="avi" audioCodec="aac" videoCodec="h264" type="Video" />
- <DirectPlayProfile container="mp4,mov" audioCodec="aac,ac3" videoCodec="h264,mpeg4" type="Video" />
- <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="wmv2,wmv3,vc1" type="Video" />
- <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
- <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
- <DirectPlayProfile container="jpeg" 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="asf" type="Video" videoCodec="wmv2" audioCodec="wmav2" estimateContentLength="true" enableMpegtsM2TsMode="false" transcodeSeekInfo="Bytes" 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>
- <ContainerProfile type="Video" container="mp4,mov">
- <Conditions>
- <ProfileCondition condition="Equals" property="Has64BitOffsets" value="false" isRequired="false" />
- </Conditions>
- </ContainerProfile>
- <ContainerProfile type="Photo">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
- <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
- </Conditions>
- </ContainerProfile>
- </ContainerProfiles>
- <CodecProfiles>
- <CodecProfile type="Video" codec="mpeg4">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="Width" value="1280" isRequired="true" />
- <ProfileCondition condition="LessThanEqual" property="Height" value="720" isRequired="true" />
- <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="false" />
- <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="5120000" isRequired="false" />
- </Conditions>
- <ApplyConditions />
- </CodecProfile>
- <CodecProfile type="Video" codec="h264">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
- <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
- <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="41" isRequired="false" />
- <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="10240000" isRequired="false" />
- </Conditions>
- <ApplyConditions />
- </CodecProfile>
- <CodecProfile type="Video" codec="wmv2,wmv3,vc1">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
- <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
- <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="false" />
- <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="15360000" isRequired="false" />
- </Conditions>
- <ApplyConditions />
- </CodecProfile>
- <CodecProfile type="VideoAudio" codec="ac3,wmav2,wmapro">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="false" />
- </Conditions>
- <ApplyConditions />
- </CodecProfile>
- <CodecProfile type="VideoAudio" codec="aac">
- <Conditions>
- <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="false" />
- <ProfileCondition condition="Equals" property="AudioProfile" value="lc" isRequired="false" />
- </Conditions>
- <ApplyConditions />
- </CodecProfile>
- </CodecProfiles>
- <ResponseProfiles>
- <ResponseProfile container="avi" type="Video" mimeType="video/avi">
- <Conditions />
- </ResponseProfile>
- </ResponseProfiles>
- <SubtitleProfiles>
- <SubtitleProfile format="srt" method="Embed" />
- </SubtitleProfiles>
-</Profile> \ No newline at end of file
diff --git a/Emby.Dlna/Profiles/Xml/Xbox One.xml b/Emby.Dlna/Profiles/Xml/Xbox One.xml
index 423327a38..635423234 100644
--- a/Emby.Dlna/Profiles/Xml/Xbox One.xml
+++ b/Emby.Dlna/Profiles/Xml/Xbox One.xml
@@ -36,10 +36,10 @@
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<XmlRootAttributes />
<DirectPlayProfiles>
- <DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg2video" type="Video" />
+ <DirectPlayProfile container="ts" audioCodec="ac3,aac,mp3" videoCodec="h264,mpeg2video,hevc" type="Video" />
<DirectPlayProfile container="avi" audioCodec="ac3,mp3" videoCodec="mpeg4" type="Video" />
<DirectPlayProfile container="avi" audioCodec="aac" videoCodec="h264" type="Video" />
- <DirectPlayProfile container="mp4,mov,mkv,m4v" audioCodec="aac,ac3" videoCodec="h264,mpeg4,mpeg2video" type="Video" />
+ <DirectPlayProfile container="mp4,mov,mkv,m4v" audioCodec="aac,ac3" videoCodec="h264,mpeg4,mpeg2video,hevc" type="Video" />
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro" videoCodec="wmv2,wmv3,vc1" type="Video" />
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index c1ab9ec22..2aeb4b971 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -996,7 +996,7 @@ namespace Emby.Server.Implementations
NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager);
RegisterSingleInstance(NotificationManager);
- SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager);
+ SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager, ServerConfigurationManager);
RegisterSingleInstance(SubtitleManager);
RegisterSingleInstance<IDeviceDiscovery>(new DeviceDiscovery(LogManager.GetLogger("IDeviceDiscovery"), ServerConfigurationManager, SocketFactory, TimerFactory));
diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs
index c42f22804..c566ca25b 100644
--- a/Emby.Server.Implementations/Channels/ChannelManager.cs
+++ b/Emby.Server.Implementations/Channels/ChannelManager.cs
@@ -296,7 +296,7 @@ namespace Emby.Server.Implementations.Channels
if (requiresCallback != null)
{
- results = await GetChannelItemMediaSourcesInternal(requiresCallback, GetItemExternalId(item), cancellationToken)
+ results = await GetChannelItemMediaSourcesInternal(requiresCallback, item.ExternalId, cancellationToken)
.ConfigureAwait(false);
}
else
@@ -990,18 +990,6 @@ namespace Emby.Server.Implementations.Channels
return result;
}
- private string GetItemExternalId(BaseItem item)
- {
- var externalId = item.ExternalId;
-
- if (string.IsNullOrWhiteSpace(externalId))
- {
- externalId = item.GetProviderId("ProviderExternalId");
- }
-
- return externalId;
- }
-
private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1);
private async Task<ChannelItemResult> GetChannelItems(IChannel channel,
User user,
@@ -1080,7 +1068,7 @@ namespace Emby.Server.Implementations.Channels
{
var categoryItem = _libraryManager.GetItemById(new Guid(folderId));
- query.FolderId = GetItemExternalId(categoryItem);
+ query.FolderId = categoryItem.ExternalId;
}
var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false);
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index 0a316fcf1..2fa09c2b1 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -373,6 +373,8 @@ namespace Emby.Server.Implementations.Dto
}
NormalizeMediaSourceContainers(dto);
+
+ dto.SupportsMediaSourceSelection = hasMediaSources.SupportsMediaSourceSelection();
}
}
diff --git a/Emby.Server.Implementations/IO/SharpCifsFileSystem.cs b/Emby.Server.Implementations/IO/SharpCifsFileSystem.cs
index 1d21796b1..0e1f6bb00 100644
--- a/Emby.Server.Implementations/IO/SharpCifsFileSystem.cs
+++ b/Emby.Server.Implementations/IO/SharpCifsFileSystem.cs
@@ -487,14 +487,17 @@ namespace Emby.Server.Implementations.IO
AssertDirectoryExists(dir, path);
var list = ListFiles(dir, recursive);
+ var result = new List<FileSystemMetadata>();
foreach (var file in list)
{
if (file.IsDirectory())
{
- yield return ToMetadata(file);
+ result.Add(ToMetadata(file));
}
}
+
+ return result;
}
public IEnumerable<FileSystemMetadata> GetFiles(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
@@ -503,6 +506,7 @@ namespace Emby.Server.Implementations.IO
AssertDirectoryExists(dir, path);
var list = ListFiles(dir, recursive);
+ var result = new List<FileSystemMetadata>();
foreach (var file in list)
{
@@ -513,10 +517,12 @@ namespace Emby.Server.Implementations.IO
if (extensions == null || extensions.Length == 0 || extensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
- yield return ToMetadata(file);
+ result.Add(ToMetadata(file));
}
}
}
+
+ return result;
}
public IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false)
@@ -525,15 +531,19 @@ namespace Emby.Server.Implementations.IO
AssertDirectoryExists(dir, path);
var list = ListFiles(dir, recursive);
+ var result = new List<FileSystemMetadata>();
foreach (var file in list)
{
- yield return ToMetadata(file);
+ result.Add(ToMetadata(file));
}
+
+ return result;
}
- public IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false)
+ public List<string> GetFileSystemEntryPaths(string path, bool recursive = false)
{
+ var result = new List<string>();
var dir = CreateSmbDirectoryForListFiles(path);
AssertDirectoryExists(dir, path);
@@ -541,16 +551,18 @@ namespace Emby.Server.Implementations.IO
foreach (var file in list)
{
- yield return GetReturnPath(file);
+ result.Add(GetReturnPath(file));
}
+ return result;
}
- public IEnumerable<string> GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
+ public List<string> GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
{
var dir = CreateSmbDirectoryForListFiles(path);
AssertDirectoryExists(dir, path);
var list = ListFiles(dir, recursive);
+ var result = new List<string>();
foreach (var file in list)
{
@@ -561,44 +573,52 @@ namespace Emby.Server.Implementations.IO
if (extensions == null || extensions.Length == 0 || extensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
- yield return filePath;
+ result.Add(filePath);
}
}
}
+
+ return result;
}
- public IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false)
+ public List<string> GetDirectoryPaths(string path, bool recursive = false)
{
var dir = CreateSmbDirectoryForListFiles(path);
AssertDirectoryExists(dir, path);
var list = ListFiles(dir, recursive);
+ var result = new List<string>();
foreach (var file in list)
{
if (file.IsDirectory())
{
- yield return GetReturnPath(file);
+ result.Add(GetReturnPath(file));
}
}
+
+ return result;
}
private IEnumerable<SmbFile> ListFiles(SmbFile dir, bool recursive)
{
var list = dir.ListFiles();
+ var result = new List<SmbFile>();
foreach (var file in list)
{
- yield return file;
+ result.Add(file);
if (recursive && file.IsDirectory())
{
foreach (var subFile in ListFiles(file, recursive))
{
- yield return subFile;
+ result.Add(subFile);
}
}
}
+
+ return result;
}
}
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
index e3200a099..7e960f85e 100644
--- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
@@ -274,7 +274,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
return false;
}
- return FileSystem.GetFilePaths(fullPath).Any(i => string.Equals(Path.GetExtension(i), ".vob", StringComparison.OrdinalIgnoreCase));
+ return directoryService.GetFilePaths(fullPath).Any(i => string.Equals(Path.GetExtension(i), ".vob", StringComparison.OrdinalIgnoreCase));
}
/// <summary>
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index be5e57539..b469966f5 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -2445,6 +2445,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
existingTimer.Status = RecordingStatus.Cancelled;
}
+ else if (!existingTimer.IsManual)
+ {
+ existingTimer.Status = RecordingStatus.New;
+ }
if (existingTimer.Status != RecordingStatus.Cancelled)
{
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index 718620ab5..7e72d1b1a 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -1232,6 +1232,8 @@ namespace Emby.Server.Implementations.LiveTv
var newChannelIdList = new List<Guid>();
var newProgramIdList = new List<Guid>();
+ var cleanDatabase = true;
+
foreach (var service in _services)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -1254,6 +1256,7 @@ namespace Emby.Server.Implementations.LiveTv
}
catch (Exception ex)
{
+ cleanDatabase = false;
_logger.ErrorException("Error refreshing channels for service", ex);
}
@@ -1264,8 +1267,11 @@ namespace Emby.Server.Implementations.LiveTv
progress.Report(100 * percent);
}
- await CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false);
- await CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false);
+ if (cleanDatabase)
+ {
+ await CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false);
+ await CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false);
+ }
var coreService = _services.OfType<EmbyTV.EmbyTV>().FirstOrDefault();
@@ -1291,8 +1297,9 @@ namespace Emby.Server.Implementations.LiveTv
{
progress.Report(10);
- var allChannels = await GetChannels(service, cancellationToken).ConfigureAwait(false);
- var allChannelsList = allChannels.ToList();
+ var allChannelsList = (await service.GetChannelsAsync(cancellationToken).ConfigureAwait(false))
+ .Select(i => new Tuple<string, ChannelInfo>(service.Name, i))
+ .ToList();
var list = new List<LiveTvChannel>();
@@ -1507,13 +1514,6 @@ namespace Emby.Server.Implementations.LiveTv
return 7;
}
- private async Task<IEnumerable<Tuple<string, ChannelInfo>>> GetChannels(ILiveTvService service, CancellationToken cancellationToken)
- {
- var channels = await service.GetChannelsAsync(cancellationToken).ConfigureAwait(false);
-
- return channels.Select(i => new Tuple<string, ChannelInfo>(service.Name, i));
- }
-
private DateTime _lastRecordingRefreshTime;
private async Task RefreshRecordings(Guid internalLiveTvFolderId, CancellationToken cancellationToken)
{
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs
index 7e0e5fc5c..1ea77d505 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs
@@ -73,9 +73,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
//OpenedMediaSource.SupportsTranscoding = true;
}
- public override void Close()
+ protected override void CloseInternal()
{
- Logger.Info("Closing HDHR live stream");
LiveStreamCancellationTokenSource.Cancel();
}
@@ -106,7 +105,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
Logger.ErrorException("Error copying live stream.", ex);
}
-
+ EnableStreamSharing = false;
await DeleteTempFile(TempFilePath).ConfigureAwait(false);
});
}
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
index 06326d26c..8b46b78be 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
@@ -105,9 +105,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
await taskCompletionSource.Task.ConfigureAwait(false);
}
- public override void Close()
+ protected override void CloseInternal()
{
- Logger.Info("Closing HDHR UDP live stream");
LiveStreamCancellationTokenSource.Cancel();
}
@@ -134,6 +133,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
openTaskCompletionSource.TrySetException(ex);
}
+ EnableStreamSharing = false;
+
try
{
await hdHomerunManager.StopStreaming().ConfigureAwait(false);
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
index 862098735..cead1def0 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
@@ -52,7 +52,16 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return Task.FromResult(true);
}
- public virtual void Close()
+ public void Close()
+ {
+ EnableStreamSharing = false;
+
+ Logger.Info("Closing " + GetType().Name);
+
+ CloseInternal();
+ }
+
+ protected virtual void CloseInternal()
{
}
diff --git a/Emby.Server.Implementations/Localization/Core/bg-BG.json b/Emby.Server.Implementations/Localization/Core/bg-BG.json
index cc7611bf4..02c03f578 100644
--- a/Emby.Server.Implementations/Localization/Core/bg-BG.json
+++ b/Emby.Server.Implementations/Localization/Core/bg-BG.json
@@ -1,7 +1,7 @@
{
"Latest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438",
"ValueSpecialEpisodeName": "\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u043d\u0438 - {0}",
- "Inherit": "Inherit",
+ "Inherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435",
"Books": "\u041a\u043d\u0438\u0433\u0438",
"Music": "\u041c\u0443\u0437\u0438\u043a\u0430",
"Games": "\u0418\u0433\u0440\u0438",
@@ -35,7 +35,7 @@
"UserDownloadingItemWithValues": "{0} is downloading {1}",
"HeaderLiveTV": "\u0422\u0435\u043b\u0435\u0432\u0438\u0437\u0438\u044f \u043d\u0430 \u0436\u0438\u0432\u043e",
"ChapterNameValue": "\u0413\u043b\u0430\u0432\u0430 {0}",
- "ScheduledTaskFailedWithName": "{0} failed",
+ "ScheduledTaskFailedWithName": "{0} \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438",
"LabelRunningTimeValue": "Running time: {0}",
"ScheduledTaskStartedWithName": "{0} \u0437\u0430\u043f\u043e\u0447\u043d\u0430",
"VersionNumber": "\u0412\u0435\u0440\u0441\u0438\u044f {0}",
@@ -49,40 +49,40 @@
"DeviceOnlineWithName": "{0} \u0435 \u0441\u0432\u044a\u0440\u0437\u0430\u043d",
"UserOnlineFromDevice": "{0} \u0435 \u043d\u0430 \u043b\u0438\u043d\u0438\u044f \u043e\u0442 {1}",
"ProviderValue": "\u0414\u043e\u0441\u0442\u0430\u0432\u0447\u0438\u043a: {0}",
- "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
- "UserCreatedWithName": "User {0} has been created",
- "UserPasswordChangedWithName": "Password has been changed for user {0}",
- "UserDeletedWithName": "User {0} has been deleted",
+ "SubtitlesDownloadedForItem": "\u0418\u0437\u0442\u0435\u0433\u043b\u0435\u043d\u0438 \u0441\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0438 \u0437\u0430 {0}",
+ "UserCreatedWithName": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f\u0442 {0} \u0435 \u0441\u044a\u0437\u0434\u0430\u0434\u0435\u043d",
+ "UserPasswordChangedWithName": "\u041f\u0430\u0440\u043e\u043b\u0430\u0442\u0430 \u043d\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f {0} \u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0435\u043d\u0430",
+ "UserDeletedWithName": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f\u0442 {0} \u0435 \u0438\u0437\u0442\u0440\u0438\u0442",
"UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
"MessageServerConfigurationUpdated": "Server configuration has been updated",
"MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
- "MessageApplicationUpdated": "Emby Server has been updated",
+ "MessageApplicationUpdated": "\u0421\u044a\u0440\u0432\u044a\u0440\u044a\u0442 \u0435 \u043e\u0431\u043d\u043e\u0432\u0435\u043d",
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
- "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
- "UserOfflineFromDevice": "{0} has disconnected from {1}",
- "DeviceOfflineWithName": "{0} has disconnected",
+ "AuthenticationSucceededWithUserName": "{0} \u0441\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e",
+ "UserOfflineFromDevice": "{0} \u0441\u0435 \u0440\u0430\u0437\u043a\u0430\u0447\u0438 \u043e\u0442 {1}",
+ "DeviceOfflineWithName": "{0} \u0441\u0435 \u0440\u0430\u0437\u043a\u0430\u0447\u0438",
"UserStartedPlayingItemWithValues": "{0} has started playing {1}",
"UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
- "NotificationOptionPluginError": "Plugin failure",
- "NotificationOptionApplicationUpdateAvailable": "Application update available",
- "NotificationOptionApplicationUpdateInstalled": "Application update installed",
+ "NotificationOptionPluginError": "\u0413\u0440\u0435\u0448\u043a\u0430 \u0432 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430",
+ "NotificationOptionApplicationUpdateAvailable": "\u041d\u0430\u043b\u0438\u0447\u043d\u043e \u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430\u0442\u0430",
+ "NotificationOptionApplicationUpdateInstalled": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430\u0442\u0430 \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u043e",
"NotificationOptionPluginUpdateInstalled": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430 \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u043e",
"NotificationOptionPluginInstalled": "\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430 \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0430",
"NotificationOptionPluginUninstalled": "\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430 \u0435 \u0434\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0430",
- "NotificationOptionVideoPlayback": "Video playback started",
- "NotificationOptionAudioPlayback": "Audio playback started",
- "NotificationOptionGamePlayback": "Game playback started",
- "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
- "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
- "NotificationOptionGamePlaybackStopped": "Game playback stopped",
- "NotificationOptionTaskFailed": "Scheduled task failure",
- "NotificationOptionInstallationFailed": "Installation failure",
+ "NotificationOptionVideoPlayback": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0432\u0438\u0434\u0435\u043e \u0437\u0430\u043f\u043e\u0447\u043d\u0430",
+ "NotificationOptionAudioPlayback": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0437\u0432\u0443\u043a \u0437\u0430\u043f\u043e\u0447\u043d\u0430",
+ "NotificationOptionGamePlayback": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0438\u0433\u0440\u0430\u0442\u0430 \u0437\u0430\u043f\u043e\u0447\u043d\u0430",
+ "NotificationOptionVideoPlaybackStopped": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0432\u0438\u0434\u0435\u043e \u0435 \u0441\u043f\u0440\u044f\u043d\u043e",
+ "NotificationOptionAudioPlaybackStopped": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0437\u0432\u0443\u043a \u0435 \u0441\u043f\u0440\u044f\u043d\u043e",
+ "NotificationOptionGamePlaybackStopped": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0438\u0433\u0440\u0430\u0442\u0430 \u0435 \u0441\u043f\u0440\u044f\u043d\u0430",
+ "NotificationOptionTaskFailed": "\u0413\u0440\u0435\u0448\u043a\u0430 \u0432 \u043f\u043b\u0430\u043d\u0438\u0440\u0430\u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0430",
+ "NotificationOptionInstallationFailed": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435",
"NotificationOptionNewLibraryContent": "\u0414\u043e\u0431\u0430\u0432\u0435\u043d\u043e \u0435 \u043d\u043e\u0432\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435",
- "NotificationOptionCameraImageUploaded": "Camera image uploaded",
+ "NotificationOptionCameraImageUploaded": "\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u0442\u043e \u043e\u0442 \u0444\u043e\u0442\u043e\u0430\u043f\u0430\u0440\u0430\u0442\u0430 \u0435 \u043a\u0430\u0447\u0435\u043d\u043e",
"NotificationOptionUserLockedOut": "User locked out",
"NotificationOptionServerRestartRequired": "\u041d\u0443\u0436\u043d\u043e \u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430",
"UserLockedOutWithName": "User {0} has been locked out",
- "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "SubtitleDownloadFailureForItem": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u0437\u0442\u0435\u0433\u043b\u044f\u043d\u0435 \u043d\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0438 \u0437\u0430 {0}",
"Sync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0430\u043d\u0435",
"User": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b",
"System": "\u0421\u0438\u0441\u0442\u0435\u043c\u0430",
diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json
index aa6ada912..0c7bce1da 100644
--- a/Emby.Server.Implementations/Localization/Core/sk.json
+++ b/Emby.Server.Implementations/Localization/Core/sk.json
@@ -2,13 +2,13 @@
"Latest": "Latest",
"ValueSpecialEpisodeName": "Special - {0}",
"Inherit": "Inherit",
- "Books": "Books",
- "Music": "Music",
- "Games": "Games",
- "Photos": "Photos",
- "MixedContent": "Mixed content",
- "MusicVideos": "Music videos",
- "HomeVideos": "Home videos",
+ "Books": "Knihy",
+ "Music": "Hudba",
+ "Games": "Hry",
+ "Photos": "Fotky",
+ "MixedContent": "Zmie\u0161an\u00fd obsah",
+ "MusicVideos": "Hudobn\u00e9 vide\u00e1",
+ "HomeVideos": "Dom\u00e1ce vide\u00e1",
"Playlists": "Playlists",
"HeaderRecordingGroups": "Recording Groups",
"HeaderContinueWatching": "Continue Watching",
@@ -16,20 +16,20 @@
"HeaderFavoriteSongs": "Ob\u013e\u00faben\u00e9 pesni\u010dky",
"HeaderAlbumArtists": "Album Artists",
"HeaderFavoriteAlbums": "Favorite Albums",
- "HeaderFavoriteEpisodes": "Favorite Episodes",
+ "HeaderFavoriteEpisodes": "Ob\u013e\u00faben\u00e9 epiz\u00f3dy",
"HeaderFavoriteShows": "Ob\u013e\u00faben\u00e9 seri\u00e1ly",
- "HeaderNextUp": "Next Up",
+ "HeaderNextUp": "Nasleduje",
"Favorites": "Ob\u013e\u00faben\u00e9",
- "Collections": "Collections",
- "Channels": "Channels",
- "Movies": "Movies",
- "Albums": "Albums",
- "Artists": "Artists",
- "Folders": "Folders",
- "Songs": "Songs",
+ "Collections": "Zbierky",
+ "Channels": "Kan\u00e1ly",
+ "Movies": "Filmy",
+ "Albums": "Albumy",
+ "Artists": "Umelci",
+ "Folders": "Prie\u010dinky",
+ "Songs": "Skladby",
"TvShows": "TV Shows",
"Shows": "Series",
- "Genres": "Genres",
+ "Genres": "\u017d\u00e1nre",
"NameSeasonNumber": "Season {0}",
"AppDeviceValues": "App: {0}, Device: {1}",
"UserDownloadingItemWithValues": "{0} is downloading {1}",
@@ -86,6 +86,6 @@
"Sync": "Sync",
"User": "User",
"System": "System",
- "Application": "Application",
+ "Application": "Aplik\u00e1cia",
"Plugin": "Plugin"
} \ No newline at end of file
diff --git a/Emby.Server.Implementations/Localization/Core/sv.json b/Emby.Server.Implementations/Localization/Core/sv.json
index c43bd79a6..ed1867024 100644
--- a/Emby.Server.Implementations/Localization/Core/sv.json
+++ b/Emby.Server.Implementations/Localization/Core/sv.json
@@ -27,7 +27,7 @@
"Artists": "Artister",
"Folders": "Mappar",
"Songs": "L\u00e5tar",
- "TvShows": "TV Shows",
+ "TvShows": "TV-serier",
"Shows": "Serier",
"Genres": "Genrer",
"NameSeasonNumber": "S\u00e4song {0}",
diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs
index 2eb4743cd..6d271c0e1 100644
--- a/Emby.Server.Implementations/Localization/LocalizationManager.cs
+++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs
@@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Localization
var localizationPath = LocalizationPath;
- _fileSystem.CreateDirectory(localizationPath);
+ _fileSystem.CreateDirectory(localizationPath);
var existingFiles = GetRatingsFiles(localizationPath)
.Select(Path.GetFileName)
@@ -91,7 +91,7 @@ namespace Emby.Server.Implementations.Localization
}
}
}
-
+
foreach (var file in GetRatingsFiles(localizationPath))
{
LoadRatings(file);
@@ -128,12 +128,20 @@ namespace Emby.Server.Implementations.Localization
return _textLocalizer.NormalizeFormKD(text);
}
+ private CultureDto[] _cultures;
+
/// <summary>
/// Gets the cultures.
/// </summary>
/// <returns>IEnumerable{CultureDto}.</returns>
public CultureDto[] GetCultures()
{
+ var result = _cultures;
+ if (result != null)
+ {
+ return result;
+ }
+
var type = GetType();
var path = type.Namespace + ".iso6392.txt";
@@ -166,10 +174,14 @@ namespace Emby.Server.Implementations.Localization
}
}
- return list.Where(i => !string.IsNullOrWhiteSpace(i.Name) &&
- !string.IsNullOrWhiteSpace(i.DisplayName) &&
- !string.IsNullOrWhiteSpace(i.ThreeLetterISOLanguageName) &&
- !string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)).ToArray();
+ result = list.Where(i => !string.IsNullOrWhiteSpace(i.Name) &&
+ !string.IsNullOrWhiteSpace(i.DisplayName) &&
+ !string.IsNullOrWhiteSpace(i.ThreeLetterISOLanguageName) &&
+ !string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)).ToArray();
+
+ _cultures = result;
+
+ return result;
}
/// <summary>
@@ -239,7 +251,7 @@ namespace Emby.Server.Implementations.Localization
/// <returns>Dictionary{System.StringParentalRating}.</returns>
private void LoadRatings(string file)
{
- var dict = _fileSystem.ReadAllLines(file).Select(i =>
+ var dict = _fileSystem.ReadAllLines(file).Select(i =>
{
if (!string.IsNullOrWhiteSpace(i))
{
@@ -269,7 +281,7 @@ namespace Emby.Server.Implementations.Localization
_allParentalRatings.TryAdd(countryCode, dict);
}
- private readonly string[] _unratedValues = {"n/a", "unrated", "not rated"};
+ private readonly string[] _unratedValues = { "n/a", "unrated", "not rated" };
/// <summary>
/// Gets the rating level.
diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
index 9a9e619a6..6e0e55bef 100644
--- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -17,6 +17,7 @@ using System.Threading.Tasks;
using MediaBrowser.Controller.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
namespace Emby.Server.Implementations.MediaEncoder
{
@@ -89,7 +90,7 @@ namespace Emby.Server.Implementations.MediaEncoder
/// </summary>
private static readonly long FirstChapterTicks = TimeSpan.FromSeconds(15).Ticks;
- public async Task<bool> RefreshChapterImages(Video video, List<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken)
+ public async Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, List<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken)
{
if (!IsEligibleForChapterImageExtraction(video))
{
@@ -101,7 +102,7 @@ namespace Emby.Server.Implementations.MediaEncoder
var runtimeTicks = video.RunTimeTicks ?? 0;
- var currentImages = GetSavedChapterImages(video);
+ var currentImages = GetSavedChapterImages(video, directoryService);
foreach (var chapter in chapters)
{
@@ -194,13 +195,13 @@ namespace Emby.Server.Implementations.MediaEncoder
return Path.Combine(GetChapterImagesPath(video), filename);
}
- private List<string> GetSavedChapterImages(Video video)
+ private List<string> GetSavedChapterImages(Video video, IDirectoryService directoryService)
{
var path = GetChapterImagesPath(video);
try
{
- return _fileSystem.GetFilePaths(path)
+ return directoryService.GetFilePaths(path)
.ToList();
}
catch (IOException)
diff --git a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs
index bf7bf9ff8..fe0652f66 100644
--- a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs
@@ -16,6 +16,7 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Tasks;
using MediaBrowser.Model.Extensions;
+using MediaBrowser.Controller.Providers;
namespace Emby.Server.Implementations.ScheduledTasks
{
@@ -120,6 +121,8 @@ namespace Emby.Server.Implementations.ScheduledTasks
previouslyFailedImages = new List<string>();
}
+ var directoryService = new DirectoryService(_fileSystem);
+
foreach (var video in videos)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -132,7 +135,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
{
var chapters = _itemRepo.GetChapters(video.Id);
- var success = await _encodingManager.RefreshChapterImages(video, chapters, extract, true, CancellationToken.None);
+ var success = await _encodingManager.RefreshChapterImages(video, directoryService, chapters, extract, true, CancellationToken.None);
if (!success)
{
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 16fd75d2e..8ef1060d1 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -51,6 +51,11 @@ namespace MediaBrowser.Controller.Entities.Audio
return 1;
}
+ public bool SupportsMediaSourceSelection()
+ {
+ return false;
+ }
+
[IgnoreDataMember]
public override bool SupportsPlayedStatus
{
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 7f6949feb..f6a8f1d5a 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -2040,7 +2040,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => i.IsLocalFile)
.Select(i => FileSystem.GetDirectoryName(i.Path))
.Distinct(StringComparer.OrdinalIgnoreCase)
- .SelectMany(i => FileSystem.GetFilePaths(i))
+ .SelectMany(i => directoryService.GetFilePaths(i))
.ToList();
var deletedImages = ImageInfos
diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs
index 54786134f..399fe9f5a 100644
--- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs
+++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs
@@ -13,5 +13,6 @@ namespace MediaBrowser.Controller.Entities
/// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution);
List<MediaStream> GetMediaStreams();
+ bool SupportsMediaSourceSelection();
}
}
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index 52f1dd051..60db53f79 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -109,6 +109,11 @@ namespace MediaBrowser.Controller.Entities
get { return true; }
}
+ public bool SupportsMediaSourceSelection()
+ {
+ return SourceType == SourceType.Library;
+ }
+
/// <summary>
/// Gets or sets the timestamp.
/// </summary>
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
index 16010b7f5..ac961d757 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
@@ -24,6 +24,11 @@ namespace MediaBrowser.Controller.LiveTv
return list;
}
+ public bool SupportsMediaSourceSelection()
+ {
+ return false;
+ }
+
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.LiveTvChannel;
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index bddafe9a6..8f8791922 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -1325,6 +1325,8 @@ namespace MediaBrowser.Controller.MediaEncoding
if (state.VideoStream != null && state.VideoStream.Width.HasValue && state.VideoStream.Height.HasValue)
{
videoSizeParam = string.Format("scale={0}:{1}", state.VideoStream.Width.Value.ToString(_usCulture), state.VideoStream.Height.Value.ToString(_usCulture));
+
+ videoSizeParam += ":force_original_aspect_ratio=decrease";
}
var mapPrefix = state.SubtitleStream.IsExternal ?
@@ -1335,7 +1337,7 @@ namespace MediaBrowser.Controller.MediaEncoding
? 0
: state.SubtitleStream.Index;
- return string.Format(" -filter_complex \"[{0}:{1}]{4}[sub] ; [0:{2}] [sub] overlay{3}\"",
+ return string.Format(" -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\"",
mapPrefix.ToString(_usCulture),
subtitleStreamIndex.ToString(_usCulture),
state.VideoStream.Index.ToString(_usCulture),
@@ -2094,6 +2096,12 @@ namespace MediaBrowser.Controller.MediaEncoding
args += " -avoid_negative_ts disabled -start_at_zero";
}
+ // This is for internal graphical subs
+ if (hasGraphicalSubs)
+ {
+ args += GetGraphicalSubtitleParam(state, encodingOptions, videoCodec);
+ }
+
var qualityParam = GetVideoQualityParam(state, videoCodec, encodingOptions, defaultH264Preset);
if (!string.IsNullOrEmpty(qualityParam))
@@ -2101,12 +2109,6 @@ namespace MediaBrowser.Controller.MediaEncoding
args += " " + qualityParam.Trim();
}
- // This is for internal graphical subs
- if (hasGraphicalSubs)
- {
- args += GetGraphicalSubtitleParam(state, encodingOptions, videoCodec);
- }
-
if (!state.RunTimeTicks.HasValue)
{
args += " -flags -global_header";
diff --git a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs
index 81269fe3f..7d50efd5e 100644
--- a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs
@@ -3,6 +3,7 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Controller.Providers;
namespace MediaBrowser.Controller.MediaEncoding
{
@@ -11,6 +12,6 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <summary>
/// Refreshes the chapter images.
/// </summary>
- Task<bool> RefreshChapterImages(Video video, List<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken);
+ Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, List<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs
index d957470d3..d673198fd 100644
--- a/MediaBrowser.Controller/Providers/DirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/DirectoryService.cs
@@ -14,11 +14,11 @@ namespace MediaBrowser.Controller.Providers
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
- private readonly ConcurrentDictionary<string, FileSystemMetadata[]> _cache =
- new ConcurrentDictionary<string, FileSystemMetadata[]>(StringComparer.OrdinalIgnoreCase);
+ private readonly Dictionary<string, FileSystemMetadata[]> _cache = new Dictionary<string, FileSystemMetadata[]>(StringComparer.OrdinalIgnoreCase);
- private readonly ConcurrentDictionary<string, FileSystemMetadata> _fileCache =
- new ConcurrentDictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase);
+ private readonly Dictionary<string, FileSystemMetadata> _fileCache = new Dictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase);
+
+ private readonly Dictionary<string, List<string>> _filePathCache = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
public DirectoryService(ILogger logger, IFileSystem fileSystem)
{
@@ -33,11 +33,6 @@ namespace MediaBrowser.Controller.Providers
public FileSystemMetadata[] GetFileSystemEntries(string path)
{
- return GetFileSystemEntries(path, false);
- }
-
- private FileSystemMetadata[] GetFileSystemEntries(string path, bool clearCache)
- {
if (string.IsNullOrWhiteSpace(path))
{
throw new ArgumentNullException("path");
@@ -45,13 +40,6 @@ namespace MediaBrowser.Controller.Providers
FileSystemMetadata[] entries;
- if (clearCache)
- {
- FileSystemMetadata[] removed;
-
- _cache.TryRemove(path, out removed);
- }
-
if (!_cache.TryGetValue(path, out entries))
{
//_logger.Debug("Getting files for " + path);
@@ -66,7 +54,8 @@ namespace MediaBrowser.Controller.Providers
entries = new FileSystemMetadata[] { };
}
- _cache.TryAdd(path, entries);
+ //_cache.TryAdd(path, entries);
+ _cache[path] = entries;
}
return entries;
@@ -74,13 +63,8 @@ namespace MediaBrowser.Controller.Providers
public List<FileSystemMetadata> GetFiles(string path)
{
- return GetFiles(path, false);
- }
-
- public List<FileSystemMetadata> GetFiles(string path, bool clearCache)
- {
var list = new List<FileSystemMetadata>();
- var items = GetFileSystemEntries(path, clearCache);
+ var items = GetFileSystemEntries(path);
foreach (var item in items)
{
if (!item.IsDirectory)
@@ -100,7 +84,8 @@ namespace MediaBrowser.Controller.Providers
if (file != null && file.Exists)
{
- _fileCache.TryAdd(path, file);
+ //_fileCache.TryAdd(path, file);
+ _fileCache[path] = file;
}
else
{
@@ -111,5 +96,24 @@ namespace MediaBrowser.Controller.Providers
return file;
//return _fileSystem.GetFileInfo(path);
}
+
+ public List<string> GetFilePaths(string path)
+ {
+ return GetFilePaths(path, false);
+ }
+
+ public List<string> GetFilePaths(string path, bool clearCache)
+ {
+ List<string> result;
+ if (clearCache || !_filePathCache.TryGetValue(path, out result))
+ {
+ result = _fileSystem.GetFilePaths(path).ToList();
+
+ _filePathCache[path] = result;
+ }
+
+ return result;
+ }
+
}
}
diff --git a/MediaBrowser.Controller/Providers/IDirectoryService.cs b/MediaBrowser.Controller/Providers/IDirectoryService.cs
index 6f864f4be..0b4574f6e 100644
--- a/MediaBrowser.Controller/Providers/IDirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/IDirectoryService.cs
@@ -8,5 +8,8 @@ namespace MediaBrowser.Controller.Providers
FileSystemMetadata[] GetFileSystemEntries(string path);
List<FileSystemMetadata> GetFiles(string path);
FileSystemMetadata GetFile(string path);
+
+ List<string> GetFilePaths(string path);
+ List<string> GetFilePaths(string path, bool clearCache);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs
index 8bad650b5..7cacb96ee 100644
--- a/MediaBrowser.Model/Dto/BaseItemDto.cs
+++ b/MediaBrowser.Model/Dto/BaseItemDto.cs
@@ -75,7 +75,8 @@ namespace MediaBrowser.Model.Dto
public bool? CanDownload { get; set; }
public bool? HasSubtitles { get; set; }
-
+ public bool? SupportsMediaSourceSelection { get; set; }
+
public string PreferredMetadataLanguage { get; set; }
public string PreferredMetadataCountryCode { get; set; }
diff --git a/MediaBrowser.Model/Providers/SubtitleOptions.cs b/MediaBrowser.Model/Providers/SubtitleOptions.cs
index 5587e897f..d0d81e1fb 100644
--- a/MediaBrowser.Model/Providers/SubtitleOptions.cs
+++ b/MediaBrowser.Model/Providers/SubtitleOptions.cs
@@ -13,6 +13,7 @@ namespace MediaBrowser.Model.Providers
public bool IsOpenSubtitleVipAccount { get; set; }
public bool RequirePerfectMatch { get; set; }
+ public bool SaveSubtitlesInMediaFolders { get; set; }
public SubtitleOptions()
{
@@ -20,6 +21,7 @@ namespace MediaBrowser.Model.Providers
SkipIfAudioTrackMatches = true;
RequirePerfectMatch = true;
+ SaveSubtitlesInMediaFolders = true;
}
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/GeneralCommandType.cs b/MediaBrowser.Model/Session/GeneralCommandType.cs
index 8dd0c29e4..616d5f9b4 100644
--- a/MediaBrowser.Model/Session/GeneralCommandType.cs
+++ b/MediaBrowser.Model/Session/GeneralCommandType.cs
@@ -39,6 +39,7 @@
ChannelDown = 31,
SetMaxStreamingBitrate = 31,
Guide = 32,
- ToggleStats = 33
+ ToggleStats = 33,
+ PlayMediaSource = 34
}
} \ No newline at end of file
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index af03e21b2..32b9a9ae2 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -27,6 +27,7 @@ namespace MediaBrowser.Providers.Manager
protected readonly IFileSystem FileSystem;
protected readonly IUserDataManager UserDataManager;
protected readonly ILibraryManager LibraryManager;
+ private readonly SubtitleResolver _subtitleResolver;
protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager)
{
@@ -36,6 +37,8 @@ namespace MediaBrowser.Providers.Manager
FileSystem = fileSystem;
UserDataManager = userDataManager;
LibraryManager = libraryManager;
+
+ _subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager, fileSystem);
}
public async Task<ItemUpdateType> RefreshMetadata(IHasMetadata item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken)
@@ -76,8 +79,7 @@ namespace MediaBrowser.Providers.Manager
if (video != null && !video.IsPlaceHolder)
{
requiresRefresh = !video.SubtitleFiles
- .SequenceEqual(SubtitleResolver.GetSubtitleFiles(video, refreshOptions.DirectoryService, FileSystem, false)
- .OrderBy(i => i), StringComparer.OrdinalIgnoreCase);
+ .SequenceEqual(_subtitleResolver.GetExternalSubtitleFiles(video, refreshOptions.DirectoryService, false), StringComparer.Ordinal);
}
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index a6a363ffd..158238557 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -229,7 +229,7 @@ namespace MediaBrowser.Providers.MediaInfo
extractDuringScan = libraryOptions.ExtractChapterImagesDuringLibraryScan;
}
- await _encodingManager.RefreshChapterImages(video, chapters, extractDuringScan, false, cancellationToken).ConfigureAwait(false);
+ await _encodingManager.RefreshChapterImages(video, options.DirectoryService, chapters, extractDuringScan, false, cancellationToken).ConfigureAwait(false);
_chapterManager.SaveChapters(video.Id.ToString(), chapters);
}
@@ -472,7 +472,7 @@ namespace MediaBrowser.Providers.MediaInfo
var subtitleResolver = new SubtitleResolver(_localization, _fileSystem);
var startIndex = currentStreams.Count == 0 ? 0 : (currentStreams.Select(i => i.Index).Max() + 1);
- var externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, startIndex, options.DirectoryService, false).ToList();
+ var externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, startIndex, options.DirectoryService, false);
var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default ||
options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
@@ -497,7 +497,7 @@ namespace MediaBrowser.Providers.MediaInfo
// Rescan
if (downloadedLanguages.Count > 0)
{
- externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, startIndex, options.DirectoryService, true).ToList();
+ externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, startIndex, options.DirectoryService, true);
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
index a2c10d6a8..4e264bd22 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
@@ -16,29 +16,91 @@ namespace MediaBrowser.Providers.MediaInfo
private readonly ILocalizationManager _localization;
private readonly IFileSystem _fileSystem;
+ private string[] SubtitleExtensions = new[]
+ {
+ ".srt",
+ ".ssa",
+ ".ass",
+ ".sub",
+ ".smi",
+ ".sami",
+ ".vtt"
+ };
+
public SubtitleResolver(ILocalizationManager localization, IFileSystem fileSystem)
{
_localization = localization;
_fileSystem = fileSystem;
}
- public IEnumerable<MediaStream> GetExternalSubtitleStreams(Video video,
+ public List<MediaStream> GetExternalSubtitleStreams(Video video,
int startIndex,
IDirectoryService directoryService,
bool clearCache)
{
- var files = GetSubtitleFiles(video, directoryService, _fileSystem, clearCache);
-
var streams = new List<MediaStream>();
- var videoFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(video.Path);
+ GetExternalSubtitleStreams(streams, video.ContainingFolderPath, video.Path, startIndex, directoryService, clearCache);
+
+ startIndex += streams.Count;
+
+ try
+ {
+ GetExternalSubtitleStreams(streams, video.GetInternalMetadataPath(), video.Path, startIndex, directoryService, clearCache);
+ }
+ catch (IOException)
+ {
+
+ }
+
+ return streams;
+ }
+
+ public List<string> GetExternalSubtitleFiles(Video video,
+ IDirectoryService directoryService,
+ bool clearCache)
+ {
+ var streams = GetExternalSubtitleStreams(video, 0, directoryService, clearCache);
+
+ var list = new List<string>();
+
+ foreach (var stream in streams)
+ {
+ list.Add(stream.Path);
+ }
+
+ return list;
+ }
+
+ private void GetExternalSubtitleStreams(List<MediaStream> streams, string folder,
+ string videoPath,
+ int startIndex,
+ IDirectoryService directoryService,
+ bool clearCache)
+ {
+ var videoFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(videoPath);
videoFileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(videoFileNameWithoutExtension);
+ var files = directoryService.GetFilePaths(folder, clearCache);
+
foreach (var fullName in files)
{
+ var extension = Path.GetExtension(fullName);
+
+ if (!SubtitleExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
var fileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(fullName);
fileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(fileNameWithoutExtension);
+ if (!string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase) &&
+ !fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
var codec = Path.GetExtension(fullName).ToLower().TrimStart('.');
if (string.Equals(codec, "txt", StringComparison.OrdinalIgnoreCase))
@@ -98,8 +160,6 @@ namespace MediaBrowser.Providers.MediaInfo
});
}
}
-
- return streams;
}
private string NormalizeFilenameForSubtitleComparison(string filename)
@@ -115,48 +175,5 @@ namespace MediaBrowser.Providers.MediaInfo
return filename;
}
-
- private static IEnumerable<string> SubtitleExtensions
- {
- get
- {
- return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami", ".vtt" };
- }
- }
-
- public static IEnumerable<string> GetSubtitleFiles(Video video, IDirectoryService directoryService, IFileSystem fileSystem, bool clearCache)
- {
- var containingPath = video.ContainingFolderPath;
-
- if (string.IsNullOrEmpty(containingPath))
- {
- throw new ArgumentException(string.Format("Cannot search for items that don't have a path: {0} {1}", video.Name, video.Id));
- }
-
- var files = fileSystem.GetFilePaths(containingPath, clearCache);
-
- var videoFileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(video.Path);
-
- return files.Where(i =>
- {
- var extension = Path.GetExtension(i);
-
- if (SubtitleExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase))
- {
- var fileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(i);
-
- if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- }
-
- return false;
- });
- }
}
}
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
index fe655759e..945498966 100644
--- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -16,8 +16,8 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-
-using MediaBrowser.Controller.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.IO;
namespace MediaBrowser.Providers.Subtitles
@@ -30,17 +30,19 @@ namespace MediaBrowser.Providers.Subtitles
private readonly ILibraryMonitor _monitor;
private readonly ILibraryManager _libraryManager;
private readonly IMediaSourceManager _mediaSourceManager;
+ private readonly IServerConfigurationManager _config;
public event EventHandler<SubtitleDownloadEventArgs> SubtitlesDownloaded;
public event EventHandler<SubtitleDownloadFailureEventArgs> SubtitleDownloadFailure;
- public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager)
+ public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager, IServerConfigurationManager config)
{
_logger = logger;
_fileSystem = fileSystem;
_monitor = monitor;
_libraryManager = libraryManager;
_mediaSourceManager = mediaSourceManager;
+ _config = config;
}
public void AddParts(IEnumerable<ISubtitleProvider> subtitleProviders)
@@ -102,6 +104,11 @@ namespace MediaBrowser.Providers.Subtitles
return results.SelectMany(i => i).ToArray();
}
+ private SubtitleOptions GetOptions()
+ {
+ return _config.GetConfiguration<SubtitleOptions>("subtitles");
+ }
+
public async Task DownloadSubtitles(Video video,
string subtitleId,
CancellationToken cancellationToken)
@@ -109,49 +116,37 @@ namespace MediaBrowser.Providers.Subtitles
var parts = subtitleId.Split(new[] { '_' }, 2);
var provider = GetProvider(parts.First());
+ var saveInMediaFolder = GetOptions().SaveSubtitlesInMediaFolders && video.SupportsLocalMetadata;
+
try
{
var response = await GetRemoteSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
using (var stream = response.Stream)
{
- var savePath = Path.Combine(_fileSystem.GetDirectoryName(video.Path),
- _fileSystem.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower());
-
- if (response.IsForced)
+ using (var memoryStream = new MemoryStream())
{
- savePath += ".forced";
- }
-
- savePath += "." + response.Format.ToLower();
+ await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
+ memoryStream.Position = 0;
- _logger.Info("Saving subtitles to {0}", savePath);
+ var savePaths = new List<string>();
+ var saveFileName = _fileSystem.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower();
- _monitor.ReportFileSystemChangeBeginning(savePath);
+ if (response.IsForced)
+ {
+ saveFileName += ".forced";
+ }
- try
- {
- //var isText = MediaStream.IsTextFormat(response.Format);
+ saveFileName += "." + response.Format.ToLower();
- using (var fs = _fileSystem.GetFileStream(savePath, FileOpenMode.Create, FileAccessMode.Write,
- FileShareMode.Read, true))
+ if (saveInMediaFolder)
{
- await stream.CopyToAsync(fs).ConfigureAwait(false);
+ savePaths.Add(Path.Combine(video.ContainingFolderPath, saveFileName));
}
- EventHelper.FireEventIfNotNull(SubtitlesDownloaded, this, new SubtitleDownloadEventArgs
- {
- Item = video,
- Format = response.Format,
- Language = response.Language,
- IsForced = response.IsForced,
- Provider = provider.Name
+ savePaths.Add(Path.Combine(video.GetInternalMetadataPath(), saveFileName));
- }, _logger);
- }
- finally
- {
- _monitor.ReportFileSystemChangeComplete(savePath, false);
+ await TrySaveToFiles(memoryStream, savePaths).ConfigureAwait(false);
}
}
}
@@ -173,6 +168,46 @@ namespace MediaBrowser.Providers.Subtitles
}
}
+ private async Task TrySaveToFiles(Stream stream, List<string> savePaths)
+ {
+ Exception exceptionToThrow = null;
+
+ foreach (var savePath in savePaths)
+ {
+ _logger.Info("Saving subtitles to {0}", savePath);
+
+ _monitor.ReportFileSystemChangeBeginning(savePath);
+
+ try
+ {
+ using (var fs = _fileSystem.GetFileStream(savePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true))
+ {
+ await stream.CopyToAsync(fs).ConfigureAwait(false);
+ }
+
+ return;
+ }
+ catch (Exception ex)
+ {
+ if (exceptionToThrow == null)
+ {
+ exceptionToThrow = ex;
+ }
+ }
+ finally
+ {
+ _monitor.ReportFileSystemChangeComplete(savePath, false);
+ }
+
+ stream.Position = 0;
+ }
+
+ if (exceptionToThrow != null)
+ {
+ throw exceptionToThrow;
+ }
+ }
+
public Task<RemoteSubtitleInfo[]> SearchSubtitles(Video video, string language, bool? isPerfectMatch, CancellationToken cancellationToken)
{
if (video.LocationType != LocationType.FileSystem ||
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 74a0759e3..0750f469e 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,3 +1,3 @@
using System.Reflection;
-[assembly: AssemblyVersion("3.2.36.1")]
+[assembly: AssemblyVersion("3.2.36.2")]