diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 59346cdec2..8cfe9de39c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -105,7 +105,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private class HdHomerunChannelInfo : ChannelInfo { public bool IsLegacyTuner { get; set; } - public string Url { get; set; } } protected override async Task> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) @@ -124,7 +123,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun VideoCodec = i.VideoCodec, ChannelType = ChannelType.TV, IsLegacyTuner = (i.URL ?? string.Empty).StartsWith("hdhomerun", StringComparison.OrdinalIgnoreCase), - Url = i.URL + Path = i.URL }).Cast().ToList(); } @@ -148,7 +147,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { using (var response = await _httpClient.SendAsync(new HttpRequestOptions() { - Url = string.Format("{0}/discover.json", GetApiUrl(info, false)), + Url = string.Format("{0}/discover.json", GetApiUrl(info)), CancellationToken = cancellationToken, TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds), BufferContent = false @@ -195,13 +194,80 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - private async Task> GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) + private async Task> GetTunerInfosHttp(TunerHostInfo info, CancellationToken cancellationToken) + { + var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); + + using (var stream = await _httpClient.Get(new HttpRequestOptions() + { + Url = string.Format("{0}/tuners.html", GetApiUrl(info)), + CancellationToken = cancellationToken, + TimeoutMs = Convert.ToInt32(TimeSpan.FromSeconds(5).TotalMilliseconds), + BufferContent = false + })) + { + var tuners = new List(); + using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8)) + { + while (!sr.EndOfStream) + { + string line = StripXML(sr.ReadLine()); + if (line.Contains("Channel")) + { + LiveTvTunerStatus status; + var index = line.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); + var name = line.Substring(0, index - 1); + var currentChannel = line.Substring(index + 7); + if (currentChannel != "none") { status = LiveTvTunerStatus.LiveTv; } else { status = LiveTvTunerStatus.Available; } + tuners.Add(new LiveTvTunerInfo + { + Name = name, + SourceType = string.IsNullOrWhiteSpace(model.ModelNumber) ? Name : model.ModelNumber, + ProgramName = currentChannel, + Status = status + }); + } + } + } + return tuners; + } + } + + private static string StripXML(string source) + { + char[] buffer = new char[source.Length]; + int bufferIndex = 0; + bool inside = false; + + for (int i = 0; i < source.Length; i++) + { + char let = source[i]; + if (let == '<') + { + inside = true; + continue; + } + if (let == '>') + { + inside = false; + continue; + } + if (!inside) + { + buffer[bufferIndex] = let; + bufferIndex++; + } + } + return new string(buffer, 0, bufferIndex); + } + + private async Task> GetTunerInfosUdp(TunerHostInfo info, CancellationToken cancellationToken) { var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); var tuners = new List(); - var uri = new Uri(GetApiUrl(info, false)); + var uri = new Uri(GetApiUrl(info)); using (var manager = new HdHomerunManager(_socketFactory, Logger)) { @@ -246,7 +312,22 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return list; } - private string GetApiUrl(TunerHostInfo info, bool isPlayback) + public async Task> GetTunerInfos(TunerHostInfo info, CancellationToken cancellationToken) + { + // TODO Need faster way to determine UDP vs HTTP + var channels = await GetChannels(info, true, cancellationToken); + + var hdHomerunChannelInfo = channels.FirstOrDefault() as HdHomerunChannelInfo; + + if (hdHomerunChannelInfo == null || hdHomerunChannelInfo.IsLegacyTuner) + { + return await GetTunerInfosUdp(info, cancellationToken).ConfigureAwait(false); + } + + return await GetTunerInfosHttp(info, cancellationToken).ConfigureAwait(false); + } + + private string GetApiUrl(TunerHostInfo info) { var url = info.Url; @@ -260,16 +341,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun url = "http://" + url; } - var uri = new Uri(url); - - if (isPlayback) - { - var builder = new UriBuilder(uri); - builder.Port = 5004; - uri = builder.Uri; - } - - return uri.AbsoluteUri.TrimEnd('/'); + return new Uri(url).AbsoluteUri.TrimEnd('/'); } private class Channels @@ -392,7 +464,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun nal = "0"; } - var url = GetApiUrl(info, false); + var url = GetApiUrl(info); var id = profile; if (string.IsNullOrWhiteSpace(id)) @@ -526,7 +598,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (hdhomerunChannel != null && hdhomerunChannel.IsLegacyTuner) { - return new HdHomerunUdpStream(mediaSource, streamId, new LegacyHdHomerunChannelCommands(hdhomerunChannel.Url), modelInfo.TunerCount, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager, _environment); + return new HdHomerunUdpStream(mediaSource, streamId, new LegacyHdHomerunChannelCommands(hdhomerunChannel.Path), modelInfo.TunerCount, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager, _environment); } // The UDP method is not working reliably on OSX, and on BSD it hasn't been tested yet @@ -537,7 +609,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { mediaSource.Protocol = MediaProtocol.Http; - var httpUrl = GetApiUrl(info, true) + "/auto/v" + hdhrId; + var httpUrl = channelInfo.Path; // If raw was used, the tuner doesn't support params if (!string.IsNullOrWhiteSpace(profile) && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 1b185b073b..54e4657c11 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -9,6 +9,8 @@ using System.Linq; using System.Threading.Tasks; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Services; +using MediaBrowser.Common.Net; +using System.Threading; namespace MediaBrowser.Api { @@ -50,14 +52,16 @@ namespace MediaBrowser.Api private readonly IUserManager _userManager; private readonly IConnectManager _connectManager; private readonly IMediaEncoder _mediaEncoder; + private readonly IHttpClient _httpClient; - public StartupWizardService(IServerConfigurationManager config, IServerApplicationHost appHost, IUserManager userManager, IConnectManager connectManager, IMediaEncoder mediaEncoder) + public StartupWizardService(IServerConfigurationManager config, IHttpClient httpClient, IServerApplicationHost appHost, IUserManager userManager, IConnectManager connectManager, IMediaEncoder mediaEncoder) { _config = config; _appHost = appHost; _userManager = userManager; _connectManager = connectManager; _mediaEncoder = mediaEncoder; + _httpClient = httpClient; } public void Post(ReportStartupWizardComplete request) @@ -65,6 +69,35 @@ namespace MediaBrowser.Api _config.Configuration.IsStartupWizardCompleted = true; _config.SetOptimalValues(); _config.SaveConfiguration(); + + Task.Run(UpdateStats); + } + + private async Task UpdateStats() + { + try + { + var url = string.Format("http://www.mb3admin.com/admin/service/package/installed?mac={0}&product=MBServer&operation=Install&version={1}", + _appHost.SystemId, + _appHost.ApplicationVersion.ToString()); + + using (var response = await _httpClient.SendAsync(new HttpRequestOptions + { + + Url = url, + CancellationToken = CancellationToken.None, + LogErrors = false, + LogRequest = false + + }, "GET").ConfigureAwait(false)) + { + + } + } + catch + { + + } } public object Get(GetStartupInfo request) diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 747528cbfe..4cdcde4120 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -46,13 +46,13 @@ namespace MediaBrowser.Model.Entities { get { - if (!string.IsNullOrEmpty(Title)) - { - return AddLanguageIfNeeded(Title); - } - if (Type == MediaStreamType.Audio) { + if (!string.IsNullOrEmpty(Title)) + { + return AddLanguageIfNeeded(Title); + } + List attributes = new List(); if (!string.IsNullOrEmpty(Language)) @@ -84,8 +84,32 @@ namespace MediaBrowser.Model.Entities return string.Join(" ", attributes.ToArray(attributes.Count)); } + if (Type == MediaStreamType.Video) + { + List attributes = new List(); + + var resolutionText = GetResolutionText(); + + if (!string.IsNullOrEmpty(resolutionText)) + { + attributes.Add(resolutionText); + } + + if (!string.IsNullOrEmpty(Codec)) + { + attributes.Add(Codec.ToUpper()); + } + + return string.Join(" ", attributes.ToArray(attributes.Count)); + } + if (Type == MediaStreamType.Subtitle) { + if (!string.IsNullOrEmpty(Title)) + { + return AddLanguageIfNeeded(Title); + } + List attributes = new List(); if (!string.IsNullOrEmpty(Language)) @@ -121,6 +145,54 @@ namespace MediaBrowser.Model.Entities } } + private string GetResolutionText() + { + var i = this; + + if (i.Width.HasValue) + { + if (i.Width >= 3800) + { + return "4K"; + } + if (i.Width >= 2500) + { + if (i.IsInterlaced) + { + return "1440I"; + } + return "1440P"; + } + if (i.Width >= 1900) + { + if (i.IsInterlaced) + { + return "1080I"; + } + return "1080P"; + } + if (i.Width >= 1260) + { + if (i.IsInterlaced) + { + return "720I"; + } + return "720P"; + } + if (i.Width >= 700) + { + + if (i.IsInterlaced) + { + return "480I"; + } + return "480P"; + } + + } + return null; + } + private string AddLanguageIfNeeded(string title) { if (!string.IsNullOrEmpty(Language) && diff --git a/MediaBrowser.Model/Providers/SubtitleOptions.cs b/MediaBrowser.Model/Providers/SubtitleOptions.cs index d0d81e1fb2..5587e897fe 100644 --- a/MediaBrowser.Model/Providers/SubtitleOptions.cs +++ b/MediaBrowser.Model/Providers/SubtitleOptions.cs @@ -13,7 +13,6 @@ namespace MediaBrowser.Model.Providers public bool IsOpenSubtitleVipAccount { get; set; } public bool RequirePerfectMatch { get; set; } - public bool SaveSubtitlesInMediaFolders { get; set; } public SubtitleOptions() { @@ -21,7 +20,6 @@ namespace MediaBrowser.Model.Providers SkipIfAudioTrackMatches = true; RequirePerfectMatch = true; - SaveSubtitlesInMediaFolders = true; } } } \ No newline at end of file diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 945498966a..6a9b7136c0 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -116,7 +116,7 @@ namespace MediaBrowser.Providers.Subtitles var parts = subtitleId.Split(new[] { '_' }, 2); var provider = GetProvider(parts.First()); - var saveInMediaFolder = GetOptions().SaveSubtitlesInMediaFolders && video.SupportsLocalMetadata; + var saveInMediaFolder = video.IsSaveLocalMetadataEnabled(); try { diff --git a/SharedVersion.cs b/SharedVersion.cs index 6403bf1cbc..f0a2b930d6 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.36.4")] +[assembly: AssemblyVersion("3.2.36.5")]