diff --git a/Emby.Common.Implementations/Net/NetSocket.cs b/Emby.Common.Implementations/Net/NetSocket.cs index 62ca3d6ac1..bc012dfe2d 100644 --- a/Emby.Common.Implementations/Net/NetSocket.cs +++ b/Emby.Common.Implementations/Net/NetSocket.cs @@ -13,7 +13,9 @@ namespace Emby.Common.Implementations.Net public Socket Socket { get; private set; } private readonly ILogger _logger; - public NetSocket(Socket socket, ILogger logger) + public bool DualMode { get; private set; } + + public NetSocket(Socket socket, ILogger logger, bool isDualMode) { if (socket == null) { @@ -26,6 +28,7 @@ namespace Emby.Common.Implementations.Net Socket = socket; _logger = logger; + DualMode = isDualMode; } public IpEndPointInfo LocalEndPoint @@ -81,7 +84,7 @@ namespace Emby.Common.Implementations.Net private SocketAcceptor _acceptor; public void StartAccept(Action onAccept, Func isClosed) { - _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed); + _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed, DualMode); _acceptor.StartAccept(); } diff --git a/Emby.Common.Implementations/Net/SocketAcceptor.cs b/Emby.Common.Implementations/Net/SocketAcceptor.cs index bddb7a079a..d4c6d33e52 100644 --- a/Emby.Common.Implementations/Net/SocketAcceptor.cs +++ b/Emby.Common.Implementations/Net/SocketAcceptor.cs @@ -11,8 +11,9 @@ namespace Emby.Common.Implementations.Net private readonly Socket _originalSocket; private readonly Func _isClosed; private readonly Action _onAccept; + private readonly bool _isDualMode; - public SocketAcceptor(ILogger logger, Socket originalSocket, Action onAccept, Func isClosed) + public SocketAcceptor(ILogger logger, Socket originalSocket, Action onAccept, Func isClosed, bool isDualMode) { if (logger == null) { @@ -34,6 +35,7 @@ namespace Emby.Common.Implementations.Net _logger = logger; _originalSocket = originalSocket; _isClosed = isClosed; + _isDualMode = isDualMode; _onAccept = onAccept; } @@ -115,7 +117,7 @@ namespace Emby.Common.Implementations.Net if (acceptSocket != null) { //ProcessAccept(acceptSocket); - _onAccept(new NetSocket(acceptSocket, _logger)); + _onAccept(new NetSocket(acceptSocket, _logger, _isDualMode)); } // Accept the next connection request diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs index 79310e0173..1f41ffff5c 100644 --- a/Emby.Common.Implementations/Net/SocketFactory.cs +++ b/Emby.Common.Implementations/Net/SocketFactory.cs @@ -46,21 +46,11 @@ namespace Emby.Common.Implementations.Net socket.DualMode = true; } - return new NetSocket(socket, _logger); + return new NetSocket(socket, _logger, dualMode); } catch (SocketException ex) { - if (dualMode) - { - _logger.Error("Error creating dual mode socket: {0}. Will retry with ipv4-only.", ex.SocketErrorCode); - - if (ex.SocketErrorCode == SocketError.AddressFamilyNotSupported) - { - return CreateSocket(IpAddressFamily.InterNetwork, socketType, protocolType, false); - } - } - - throw; + throw new SocketCreateException(ex.SocketErrorCode.ToString(), ex); } } diff --git a/Emby.Server.Core/ApplicationHost.cs b/Emby.Server.Core/ApplicationHost.cs index f7fe02fbaa..06c761f218 100644 --- a/Emby.Server.Core/ApplicationHost.cs +++ b/Emby.Server.Core/ApplicationHost.cs @@ -1305,19 +1305,49 @@ namespace Emby.Server.Core public async Task> GetLocalIpAddresses() { - var addresses = NetworkManager.GetLocalIpAddresses().ToList(); - var list = new List(); + var addresses = ServerConfigurationManager + .Configuration + .LocalNetworkAddresses + .Select(NormalizeConfiguredLocalAddress) + .Where(i => i != null) + .ToList(); - foreach (var address in addresses) + if (addresses.Count == 0) { - var valid = await IsIpAddressValidAsync(address).ConfigureAwait(false); - if (valid) + addresses.AddRange(NetworkManager.GetLocalIpAddresses()); + + var list = new List(); + + foreach (var address in addresses) { - list.Add(address); + var valid = await IsIpAddressValidAsync(address).ConfigureAwait(false); + if (valid) + { + list.Add(address); + } } + + addresses = list; } - return list; + return addresses; + } + + private IpAddressInfo NormalizeConfiguredLocalAddress(string address) + { + var index = address.Trim('/').IndexOf('/'); + + if (index != -1) + { + address = address.Substring(index + 1); + } + + IpAddressInfo result; + if (NetworkManager.TryParseIpAddress(address.Trim('/'), out result)) + { + return result; + } + return null; } private readonly ConcurrentDictionary _validAddressResults = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); @@ -1553,7 +1583,8 @@ namespace Emby.Server.Core throw new NotImplementedException(); } - var process = ProcessFactory.Create(new ProcessOptions { + var process = ProcessFactory.Create(new ProcessOptions + { FileName = url, EnableRaisingEvents = true, UseShellExecute = true, diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 438fc55d77..2b2c3e000d 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1351,6 +1351,27 @@ namespace Emby.Server.Implementations.Dto if (episodeSeries != null) { dto.SeriesStudio = episodeSeries.Studios.FirstOrDefault(); + if (!string.IsNullOrWhiteSpace(dto.SeriesStudio)) + { + try + { + var studio = _libraryManager.GetStudio(dto.SeriesStudio); + + if (studio != null) + { + dto.SeriesStudioInfo = new StudioDto + { + Name = dto.SeriesStudio, + Id = studio.Id.ToString("N"), + PrimaryImageTag = GetImageCacheTag(studio, ImageType.Primary) + }; + } + } + catch (Exception ex) + { + + } + } } } } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index d96756ce1b..3db8c7213c 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -341,13 +341,13 @@ namespace Emby.Server.Implementations.Library } if (item is IItemByName) { - if (!(item is MusicArtist)) + if (!(item is MusicArtist) && !(item is Studio)) { return; } } - if (item.IsFolder) + else if (item.IsFolder) { //if (!(item is ICollectionFolder) && !(item is UserView) && !(item is Channel) && !(item is AggregateFolder)) //{ diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 4e5b8d34f0..4e2b3f661f 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1594,7 +1594,17 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private void Process_Exited(object sender, EventArgs e) { - ((IProcess)sender).Dispose(); + var process = (IProcess)sender; + try + { + _logger.Info("Recording post-processing script completed with exit code {0}", process.ExitCode); + } + catch + { + + } + + process.Dispose(); } private async Task SaveRecordingImage(string recordingPath, LiveTvProgram program, ItemImageInfo image) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 2d75367d96..77efe8585b 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -377,7 +377,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var url = GetApiUrl(info, true) + "/auto/v" + channelId; - if (!string.IsNullOrWhiteSpace(profile) && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) + // If raw was used, the tuner doesn't support params + if (!string.IsNullOrWhiteSpace(profile) + && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) { url += "?transcode=" + profile; } @@ -451,16 +453,16 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } var hdhrId = GetHdHrIdFromChannelId(channelId); - list.Add(await GetMediaSource(info, hdhrId, "native").ConfigureAwait(false)); - try { - if (info.AllowHWTranscoding) + var model = await GetModelInfo(info, cancellationToken).ConfigureAwait(false); + model = model ?? string.Empty; + + if ((model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1)) { - string model = await GetModelInfo(info, cancellationToken).ConfigureAwait(false); - model = model ?? string.Empty; + list.Add(await GetMediaSource(info, hdhrId, "native").ConfigureAwait(false)); - if ((model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1)) + if (info.AllowHWTranscoding) { list.Add(await GetMediaSource(info, hdhrId, "heavy").ConfigureAwait(false)); @@ -477,6 +479,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } + if (list.Count == 0) + { + list.Add(await GetMediaSource(info, hdhrId, "native").ConfigureAwait(false)); + } + return list; } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index e4e0519de3..e0f0402813 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -100,16 +101,23 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts extInf = extInf.Trim(); - channel.ImageUrl = FindProperty("tvg-logo", extInf); + string remaining; + var attributes = ParseExtInf(extInf, out remaining); + extInf = remaining; - channel.Name = GetChannelName(extInf); + string value; + if (attributes.TryGetValue("tvg-logo", out value)) + { + channel.ImageUrl = value; + } - channel.Number = GetChannelNumber(extInf, mediaUrl); + channel.Name = GetChannelName(extInf, attributes); + channel.Number = GetChannelNumber(extInf, attributes, mediaUrl); return channel; } - private string GetChannelNumber(string extInf, string mediaUrl) + private string GetChannelNumber(string extInf, Dictionary attributes, string mediaUrl) { var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null; @@ -130,18 +138,41 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } } - if (string.IsNullOrWhiteSpace(numberString) || + if (!string.IsNullOrWhiteSpace(numberString)) + { + numberString = numberString.Trim(); + } + + if (string.IsNullOrWhiteSpace(numberString) || string.Equals(numberString, "-1", StringComparison.OrdinalIgnoreCase) || string.Equals(numberString, "0", StringComparison.OrdinalIgnoreCase)) { - numberString = FindProperty("tvg-id", extInf); + string value; + if (attributes.TryGetValue("tvg-id", out value)) + { + numberString = value; + } + } + + if (!string.IsNullOrWhiteSpace(numberString)) + { + numberString = numberString.Trim(); } if (string.IsNullOrWhiteSpace(numberString) || string.Equals(numberString, "-1", StringComparison.OrdinalIgnoreCase) || string.Equals(numberString, "0", StringComparison.OrdinalIgnoreCase)) { - numberString = FindProperty("channel-id", extInf); + string value; + if (attributes.TryGetValue("channel-id", out value)) + { + numberString = value; + } + } + + if (!string.IsNullOrWhiteSpace(numberString)) + { + numberString = numberString.Trim(); } if (string.IsNullOrWhiteSpace(numberString) || @@ -160,13 +191,19 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts else { numberString = Path.GetFileNameWithoutExtension(mediaUrl.Split('/').Last()); + + double value; + if (!double.TryParse(numberString, NumberStyles.Any, CultureInfo.InvariantCulture, out value)) + { + numberString = null; + } } } return numberString; } - private string GetChannelName(string extInf) + private string GetChannelName(string extInf, Dictionary attributes) { var nameParts = extInf.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null; @@ -186,7 +223,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } } - var name = FindProperty("tvg-name", extInf); + string name; + attributes.TryGetValue("tvg-name", out name); + if (string.IsNullOrWhiteSpace(name)) { name = nameInExtInf; @@ -194,7 +233,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (string.IsNullOrWhiteSpace(name)) { - name = FindProperty("tvg-id", extInf); + attributes.TryGetValue("tvg-id", out name); } if (string.IsNullOrWhiteSpace(name)) @@ -205,18 +244,27 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return name; } - private string FindProperty(string property, string properties) + private Dictionary ParseExtInf(string line, out string remaining) { + var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); + var reg = new Regex(@"([a-z0-9\-_]+)=\""([^""]+)\""", RegexOptions.IgnoreCase); - var matches = reg.Matches(properties); + var matches = reg.Matches(line); + var minIndex = int.MaxValue; foreach (Match match in matches) { - if (match.Groups[1].Value == property) - { - return match.Groups[2].Value; - } + dict[match.Groups[1].Value] = match.Groups[2].Value; + minIndex = Math.Min(minIndex, match.Index); } - return null; + + if (minIndex > 0 && minIndex < line.Length) + { + line = line.Substring(0, minIndex); + } + + remaining = line; + + return dict; } } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 690acb1630..84f3955185 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -258,7 +258,7 @@ namespace MediaBrowser.Api.Playback.Hls // add when stream copying? // -avoid_negative_ts make_zero -fflags +genpts - var args = string.Format("{0} {1} {2} -map_metadata -1 -threads {3} {4} {5} -fflags +genpts -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9}{10} -y \"{11}\"", + var args = string.Format("{0} {1} {2} -map_metadata -1 -map_chapters -1 -threads {3} {4} {5} -fflags +genpts -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9}{10} -y \"{11}\"", itsOffset, inputModifier, GetInputArgument(state), diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index ab2cab2241..df3e61213f 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -895,7 +895,7 @@ namespace MediaBrowser.Api.Playback.Hls { var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state); - return string.Format("{0} {10} {1} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} -break_non_keyframes 1 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", + return string.Format("{0} {10} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} -break_non_keyframes 1 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", inputModifier, GetInputArgument(state), threads, @@ -913,7 +913,7 @@ namespace MediaBrowser.Api.Playback.Hls var splitByTime = hlsProtocolSupportsSplittingByTime && enableSplittingOnNonKeyFrames; var splitByTimeArg = splitByTime ? " -hls_flags split_by_time" : ""; - return string.Format("{0}{12} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7}{8} -start_number {9} -hls_list_size {10} -y \"{11}\"", + return string.Format("{0}{12} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7}{8} -start_number {9} -hls_list_size {10} -y \"{11}\"", inputModifier, GetInputArgument(state), threads, diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 7ba1fecfec..e29aa7d5aa 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -111,7 +111,7 @@ namespace MediaBrowser.Api.Playback.Progressive var inputModifier = GetInputModifier(state); - return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -threads {5} {6}{7} -y \"{8}\"", + return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -map_chapters -1 -threads {5} {6}{7} -y \"{8}\"", inputModifier, GetInputArgument(state), keyFrame, diff --git a/MediaBrowser.Api/Reports/Common/ReportViewType.cs b/MediaBrowser.Api/Reports/Common/ReportViewType.cs index a5ffc7085f..8593c8e843 100644 --- a/MediaBrowser.Api/Reports/Common/ReportViewType.cs +++ b/MediaBrowser.Api/Reports/Common/ReportViewType.cs @@ -3,7 +3,6 @@ namespace MediaBrowser.Api.Reports public enum ReportViewType { ReportData, - ReportStatistics, ReportActivities } diff --git a/MediaBrowser.Api/Reports/ReportRequests.cs b/MediaBrowser.Api/Reports/ReportRequests.cs index b4450aa401..3627956588 100644 --- a/MediaBrowser.Api/Reports/ReportRequests.cs +++ b/MediaBrowser.Api/Reports/ReportRequests.cs @@ -60,7 +60,7 @@ namespace MediaBrowser.Api.Reports { /// Gets or sets the report view. /// The report view. - [ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + [ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] public string ReportView { get; set; } /// Gets or sets the report view. @@ -101,7 +101,7 @@ namespace MediaBrowser.Api.Reports { /// Gets or sets the report view. /// The report view. - [ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + [ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] public string ReportView { get; set; } /// Gets or sets the report view. @@ -120,13 +120,6 @@ namespace MediaBrowser.Api.Reports public string ReportColumns { get; set; } } - [Route("/Reports/Statistics", "GET", Summary = "Gets reports statistics based on library items")] - public class GetReportStatistics : BaseReportRequest, IReturn - { - public int? TopItems { get; set; } - - } - [Route("/Reports/Items/Download", "GET", Summary = "Downloads report")] public class GetReportDownload : BaseReportRequest, IReportsDownload { @@ -150,7 +143,7 @@ namespace MediaBrowser.Api.Reports { /// Gets or sets the report view. /// The report view. - [ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportStatistics, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] + [ApiMember(Name = "ReportView", Description = "The report view. Values (ReportData, ReportActivities)", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] public string ReportView { get; set; } /// Gets or sets the report view. diff --git a/MediaBrowser.Api/Reports/ReportsService.cs b/MediaBrowser.Api/Reports/ReportsService.cs index b512a822ba..5c4d21d66b 100644 --- a/MediaBrowser.Api/Reports/ReportsService.cs +++ b/MediaBrowser.Api/Reports/ReportsService.cs @@ -82,8 +82,6 @@ namespace MediaBrowser.Api.Reports ReportBuilder dataBuilder = new ReportBuilder(_libraryManager); result = dataBuilder.GetHeaders(request); break; - case ReportViewType.ReportStatistics: - break; case ReportViewType.ReportActivities: ReportActivitiesBuilder activityBuilder = new ReportActivitiesBuilder(_libraryManager, _userManager); result = activityBuilder.GetHeaders(request); @@ -109,20 +107,6 @@ namespace MediaBrowser.Api.Reports return ToOptimizedResult(reportResult); } - /// Gets the given request. - /// The request. - /// A Task<object> - public async Task Get(GetReportStatistics request) - { - if (string.IsNullOrEmpty(request.IncludeItemTypes)) - return null; - request.DisplayType = "Screen"; - var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; - var reportResult = await GetReportStatistic(request, user); - - return ToOptimizedResult(reportResult); - } - /// Gets the given request. /// The request. /// A Task<object> @@ -155,7 +139,6 @@ namespace MediaBrowser.Api.Reports ReportResult result = null; switch (reportViewType) { - case ReportViewType.ReportStatistics: case ReportViewType.ReportData: ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes); ReportBuilder dataBuilder = new ReportBuilder(_libraryManager); @@ -463,20 +446,6 @@ namespace MediaBrowser.Api.Reports return reportResult; } - /// Gets report statistic. - /// The request. - /// The report statistic. - private async Task GetReportStatistic(GetReportStatistics request, User user) - { - ReportIncludeItemTypes reportRowType = ReportHelper.GetRowType(request.IncludeItemTypes); - QueryResult queryResult = await GetQueryResult(request, user).ConfigureAwait(false); - - ReportStatBuilder reportBuilder = new ReportStatBuilder(_libraryManager); - ReportStatResult reportResult = reportBuilder.GetResult(queryResult.Items, ReportHelper.GetRowType(request.IncludeItemTypes), request.TopItems ?? 5); - reportResult.TotalRecordCount = reportResult.Groups.Count(); - return reportResult; - } - #endregion } diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 2bcccf5e8b..737257898d 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -3,6 +3,7 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using MediaBrowser.Model.Serialization; @@ -184,7 +185,16 @@ namespace MediaBrowser.Controller.Entities.TV public string FindSeasonName() { - var season = Season; + var season = Season; + + if (season == null) + { + if (ParentIndexNumber.HasValue) + { + return "Season " + ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture); + } + } + return season == null ? SeasonName : season.Name; } diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 8193e6afd7..f7b7fa5f26 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -59,7 +59,6 @@ - diff --git a/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs deleted file mode 100644 index f430df2971..0000000000 --- a/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.IO; -using System.Threading; -using MediaBrowser.Common.IO; -using MediaBrowser.Model.IO; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.IO; -using MediaBrowser.Controller.Providers; -using MediaBrowser.LocalMetadata.Parsers; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Xml; - -namespace MediaBrowser.LocalMetadata.Providers -{ - //public class PersonXmlProvider : BaseXmlProvider - //{ - // private readonly ILogger _logger; - // private readonly IProviderManager _providerManager; - // protected IXmlReaderSettingsFactory XmlReaderSettingsFactory { get; private set; } - - // public PersonXmlProvider(IFileSystem fileSystem, ILogger logger, IProviderManager providerManager, IXmlReaderSettingsFactory xmlReaderSettingsFactory) - // : base(fileSystem) - // { - // _logger = logger; - // _providerManager = providerManager; - // XmlReaderSettingsFactory = xmlReaderSettingsFactory; - // } - - // protected override void Fetch(MetadataResult result, string path, CancellationToken cancellationToken) - // { - // new BaseItemXmlParser(_logger, _providerManager, XmlReaderSettingsFactory, FileSystem).Fetch(result, path, cancellationToken); - // } - - // protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService) - // { - // return directoryService.GetFile(Path.Combine(info.Path, "person.xml")); - // } - //} -} diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 8a3396e272..864123bb91 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -729,6 +729,8 @@ namespace MediaBrowser.Model.Dto /// The series studio. public string SeriesStudio { get; set; } + public StudioDto SeriesStudioInfo { get; set; } + /// /// Gets or sets the parent thumb item id. /// diff --git a/MediaBrowser.Model/Net/ISocket.cs b/MediaBrowser.Model/Net/ISocket.cs index 371fbc5675..aed35bce89 100644 --- a/MediaBrowser.Model/Net/ISocket.cs +++ b/MediaBrowser.Model/Net/ISocket.cs @@ -4,6 +4,7 @@ namespace MediaBrowser.Model.Net { public interface ISocket : IDisposable { + bool DualMode { get; } IpEndPointInfo LocalEndPoint { get; } IpEndPointInfo RemoteEndPoint { get; } void Close(); @@ -13,4 +14,15 @@ namespace MediaBrowser.Model.Net void StartAccept(Action onAccept, Func isClosed); } + + public class SocketCreateException : Exception + { + public SocketCreateException(string errorCode, Exception originalException) + : base(errorCode, originalException) + { + ErrorCode = errorCode; + } + + public string ErrorCode { get; private set; } + } } diff --git a/RSSDP/SsdpDevicePublisherBase.cs b/RSSDP/SsdpDevicePublisherBase.cs index ee33359574..260c008960 100644 --- a/RSSDP/SsdpDevicePublisherBase.cs +++ b/RSSDP/SsdpDevicePublisherBase.cs @@ -249,7 +249,7 @@ namespace Rssdp.Infrastructure if (IsDuplicateSearchRequest(searchTarget, remoteEndPoint)) { - WriteTrace("Search Request is Duplicate, ignoring."); + //WriteTrace("Search Request is Duplicate, ignoring."); return; } @@ -299,7 +299,9 @@ namespace Rssdp.Infrastructure } } else + { WriteTrace(String.Format("Sending 0 search responses.")); + } }); } diff --git a/SocketHttpListener.Portable/Net/EndPointListener.cs b/SocketHttpListener.Portable/Net/EndPointListener.cs index 52385e2ba7..690dedd092 100644 --- a/SocketHttpListener.Portable/Net/EndPointListener.cs +++ b/SocketHttpListener.Portable/Net/EndPointListener.cs @@ -26,7 +26,7 @@ namespace SocketHttpListener.Net Dictionary unregistered; private readonly ILogger _logger; private bool _closed; - private readonly bool _enableDualMode; + private bool _enableDualMode; private readonly ICryptoProvider _cryptoProvider; private readonly IStreamFactory _streamFactory; private readonly ISocketFactory _socketFactory; @@ -65,7 +65,23 @@ namespace SocketHttpListener.Net private void CreateSocket() { - sock = _socketFactory.CreateSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode); + try + { + sock = _socketFactory.CreateSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode); + } + catch (SocketCreateException ex) + { + if (_enableDualMode && endpoint.IpAddress.Equals(IpAddressInfo.IPv6Any) && string.Equals(ex.ErrorCode, "AddressFamilyNotSupported", StringComparison.OrdinalIgnoreCase)) + { + endpoint = new IpEndPointInfo(IpAddressInfo.Any, endpoint.Port); + _enableDualMode = false; + sock = _socketFactory.CreateSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode); + } + else + { + throw; + } + } sock.Bind(endpoint);