From 0375990d8e6b0ebfb58c318fdb4255326d72d75d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 30 Aug 2016 14:17:37 -0400 Subject: Support grabbing channel number from url --- .../LiveTv/TunerHosts/M3uParser.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index ffe95c862a..8095a6989b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -70,7 +71,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts } else if (!string.IsNullOrWhiteSpace(extInf) && !line.StartsWith("#", StringComparison.OrdinalIgnoreCase)) { - var channel = GetChannelnfo(extInf, tunerHostId); + var channel = GetChannelnfo(extInf, tunerHostId, line); channel.Id = channelIdPrefix + urlHash + line.GetMD5().ToString("N"); channel.Path = line; channels.Add(channel); @@ -79,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts } return channels; } - private M3UChannel GetChannelnfo(string extInf, string tunerHostId) + private M3UChannel GetChannelnfo(string extInf, string tunerHostId, string mediaUrl) { var titleIndex = extInf.LastIndexOf(','); var channel = new M3UChannel(); @@ -87,8 +88,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts channel.Number = extInf.Trim().Split(' ')[0] ?? "0"; channel.Name = extInf.Substring(titleIndex + 1); - - if(channel.Number == "-1") { channel.Number = "0"; } //Check for channel number with the format from SatIp int number; @@ -101,6 +100,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts channel.Name = channel.Name.Substring(numberIndex + 1); } } + + if (string.Equals(channel.Number, "-1", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(mediaUrl)) + { + channel.Number = Path.GetFileNameWithoutExtension(mediaUrl.Split('/').Last()); + } + + if (string.Equals(channel.Number, "-1", StringComparison.OrdinalIgnoreCase)) + { + channel.Number = "0"; + } + channel.ImageUrl = FindProperty("tvg-logo", extInf, null); channel.Number = FindProperty("tvg-id", extInf, channel.Number); channel.Number = FindProperty("channel-id", extInf, channel.Number); -- cgit v1.2.3 From eefd697b85fcaa76fe8f7165ea48793b8477c91d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 31 Aug 2016 15:17:11 -0400 Subject: update app footer --- .../HttpServer/HttpListenerHost.cs | 7 +++- .../LiveTv/EmbyTV/EmbyTV.cs | 46 +++++++++++----------- .../ApplicationHost.cs | 3 +- .../Browser/BrowserLauncher.cs | 5 +++ .../MediaBrowser.Server.Startup.Common.csproj | 1 - .../Migrations/OmdbEpisodeProviderMigration.cs | 43 -------------------- MediaBrowser.ServerApplication/ServerNotifyIcon.cs | 15 +++++++ 7 files changed, 49 insertions(+), 71 deletions(-) delete mode 100644 MediaBrowser.Server.Startup.Common/Migrations/OmdbEpisodeProviderMigration.cs (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 51a53fe211..28b7824c8d 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -71,14 +71,17 @@ namespace MediaBrowser.Server.Implementations.HttpServer HostConfig.Instance.MapExceptionToStatusCode = new Dictionary { - {typeof (InvalidOperationException), 422}, + {typeof (InvalidOperationException), 500}, + {typeof (NotImplementedException), 500}, {typeof (ResourceNotFoundException), 404}, {typeof (FileNotFoundException), 404}, {typeof (DirectoryNotFoundException), 404}, {typeof (SecurityException), 401}, {typeof (PaymentRequiredException), 402}, {typeof (UnauthorizedAccessException), 500}, - {typeof (ApplicationException), 500} + {typeof (ApplicationException), 500}, + {typeof (PlatformNotSupportedException), 500}, + {typeof (NotSupportedException), 500} }; HostConfig.Instance.GlobalResponseHeaders = new Dictionary(); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 6acb0783eb..649024d160 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -851,29 +851,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV var recordPath = RecordingPath; var config = GetConfiguration(); - if (info.IsMovie) - { - var customRecordingPath = config.MovieRecordingPath; - var allowSubfolder = true; - if (!string.IsNullOrWhiteSpace(customRecordingPath)) - { - allowSubfolder = string.Equals(customRecordingPath, recordPath, StringComparison.OrdinalIgnoreCase); - recordPath = customRecordingPath; - } - - if (allowSubfolder && config.EnableRecordingSubfolders) - { - recordPath = Path.Combine(recordPath, "Movies"); - } - - var folderName = _fileSystem.GetValidFilename(info.Name).Trim(); - if (info.ProductionYear.HasValue) - { - folderName += " (" + info.ProductionYear.Value.ToString(CultureInfo.InvariantCulture) + ")"; - } - recordPath = Path.Combine(recordPath, folderName); - } - else if (info.IsSeries) + if (info.IsSeries) { var customRecordingPath = config.SeriesRecordingPath; var allowSubfolder = true; @@ -910,6 +888,28 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV recordPath = Path.Combine(recordPath, folderName); } } + else if (info.IsMovie) + { + var customRecordingPath = config.MovieRecordingPath; + var allowSubfolder = true; + if (!string.IsNullOrWhiteSpace(customRecordingPath)) + { + allowSubfolder = string.Equals(customRecordingPath, recordPath, StringComparison.OrdinalIgnoreCase); + recordPath = customRecordingPath; + } + + if (allowSubfolder && config.EnableRecordingSubfolders) + { + recordPath = Path.Combine(recordPath, "Movies"); + } + + var folderName = _fileSystem.GetValidFilename(info.Name).Trim(); + if (info.ProductionYear.HasValue) + { + folderName += " (" + info.ProductionYear.Value.ToString(CultureInfo.InvariantCulture) + ")"; + } + recordPath = Path.Combine(recordPath, folderName); + } else if (info.IsKids) { if (config.EnableRecordingSubfolders) diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 36bfa56611..170719b0fa 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -382,7 +382,6 @@ namespace MediaBrowser.Server.Startup.Common { var migrations = new List { - new OmdbEpisodeProviderMigration(ServerConfigurationManager), new MovieDbEpisodeProviderMigration(ServerConfigurationManager), new DbMigration(ServerConfigurationManager, TaskManager), new UpdateLevelMigration(ServerConfigurationManager, this, HttpClient, JsonSerializer, _releaseAssetFilename) @@ -947,7 +946,7 @@ namespace MediaBrowser.Server.Startup.Common { if (!CanSelfRestart) { - throw new InvalidOperationException("The server is unable to self-restart. Please restart manually."); + throw new PlatformNotSupportedException("The server is unable to self-restart. Please restart manually."); } try diff --git a/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs b/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs index 6b3602a73d..1a0e2d9731 100644 --- a/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs +++ b/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs @@ -28,6 +28,11 @@ namespace MediaBrowser.Server.Startup.Common.Browser OpenUrl(appHost, "http://emby.media/community"); } + public static void OpenEmbyPremiere(IServerApplicationHost appHost) + { + OpenDashboardPage("supporterkey.html", appHost); + } + /// /// Opens the web client. /// diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index c415dec8af..778002e502 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -73,7 +73,6 @@ - diff --git a/MediaBrowser.Server.Startup.Common/Migrations/OmdbEpisodeProviderMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/OmdbEpisodeProviderMigration.cs deleted file mode 100644 index ebc0e67de0..0000000000 --- a/MediaBrowser.Server.Startup.Common/Migrations/OmdbEpisodeProviderMigration.cs +++ /dev/null @@ -1,43 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using System.Linq; - -namespace MediaBrowser.Server.Startup.Common.Migrations -{ - class OmdbEpisodeProviderMigration : IVersionMigration - { - private readonly IServerConfigurationManager _config; - private const string _providerName = "The Open Movie Database"; - - public OmdbEpisodeProviderMigration(IServerConfigurationManager config) - { - _config = config; - } - - public void Run() - { - var migrationKey = this.GetType().FullName; - var migrationKeyList = _config.Configuration.Migrations.ToList(); - - if (!migrationKeyList.Contains(migrationKey)) - { - foreach (var metaDataOption in _config.Configuration.MetadataOptions) - { - if (metaDataOption.ItemType == "Episode") - { - var disabledFetchers = metaDataOption.DisabledMetadataFetchers.ToList(); - if (!disabledFetchers.Contains(_providerName)) - { - disabledFetchers.Add(_providerName); - metaDataOption.DisabledMetadataFetchers = disabledFetchers.ToArray(); - } - } - } - - migrationKeyList.Add(migrationKey); - _config.Configuration.Migrations = migrationKeyList.ToArray(); - _config.SaveConfiguration(); - } - - } - } -} diff --git a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs index d04128a18c..7805c0d685 100644 --- a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs +++ b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs @@ -20,6 +20,7 @@ namespace MediaBrowser.ServerApplication private ToolStripMenuItem cmdRestart; private ToolStripSeparator toolStripSeparator1; private ToolStripMenuItem cmdCommunity; + private ToolStripMenuItem cmdPremiere; private Container components; private readonly ILogger _logger; @@ -50,6 +51,7 @@ namespace MediaBrowser.ServerApplication cmdExit = new ToolStripMenuItem(); cmdCommunity = new ToolStripMenuItem(); + cmdPremiere = new ToolStripMenuItem(); toolStripSeparator1 = new ToolStripSeparator(); cmdRestart = new ToolStripMenuItem(); toolStripSeparator2 = new ToolStripSeparator(); @@ -69,6 +71,7 @@ namespace MediaBrowser.ServerApplication contextMenuStrip1.Items.AddRange(new ToolStripItem[] { cmdBrowse, cmdConfigure, + cmdPremiere, toolStripSeparator2, cmdRestart, toolStripSeparator1, @@ -89,6 +92,11 @@ namespace MediaBrowser.ServerApplication cmdCommunity.Name = "cmdCommunity"; cmdCommunity.Size = new System.Drawing.Size(208, 22); // + // cmdPremiere + // + cmdPremiere.Name = "cmdPremiere"; + cmdPremiere.Size = new System.Drawing.Size(208, 22); + // // toolStripSeparator1 // toolStripSeparator1.Name = "toolStripSeparator1"; @@ -118,6 +126,7 @@ namespace MediaBrowser.ServerApplication cmdRestart.Click += cmdRestart_Click; cmdConfigure.Click += cmdConfigure_Click; cmdCommunity.Click += cmdCommunity_Click; + cmdPremiere.Click += cmdPremiere_Click; cmdBrowse.Click += cmdBrowse_Click; _configurationManager.ConfigurationUpdated += Instance_ConfigurationUpdated; @@ -138,6 +147,7 @@ namespace MediaBrowser.ServerApplication cmdExit.Text = _localization.GetLocalizedString("LabelExit"); cmdCommunity.Text = _localization.GetLocalizedString("LabelVisitCommunity"); + cmdPremiere.Text = _localization.GetLocalizedString("Emby Premiere"); cmdBrowse.Text = _localization.GetLocalizedString("LabelBrowseLibrary"); cmdConfigure.Text = _localization.GetLocalizedString("LabelConfigureServer"); cmdRestart.Text = _localization.GetLocalizedString("LabelRestartServer"); @@ -163,6 +173,11 @@ namespace MediaBrowser.ServerApplication BrowserLauncher.OpenWebClient(_appHost); } + void cmdPremiere_Click(object sender, EventArgs e) + { + BrowserLauncher.OpenEmbyPremiere(_appHost); + } + void cmdCommunity_Click(object sender, EventArgs e) { BrowserLauncher.OpenCommunity(_appHost); -- cgit v1.2.3 From fb251448c90ac8905a9f9ad6ec9a1b676aa51922 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 1 Sep 2016 21:54:16 -0400 Subject: Rtp Rtcp fix Discovery #2116 --- .../LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs | 79 ++++++++ .../LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs | 68 +++++++ .../LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs | 59 ++++++ .../LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs | 203 +++++++++++++++++++++ .../LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs | 37 ++++ .../SatIp/Rtcp/RtcpReceiverReportPacket.cs | 68 +++++++ .../SatIp/Rtcp/RtcpSenderReportPacket.cs | 105 +++++++++++ .../SatIp/Rtcp/RtcpSourceDescriptionPacket.cs | 57 ++++++ .../SatIp/Rtcp/SourceDescriptionBlock.cs | 65 +++++++ .../TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs | 60 ++++++ .../LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs | 160 ++++++++++++++++ .../LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs | 116 ++++++++++++ .../LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs | 32 ++-- .../LiveTv/TunerHosts/SatIp/TransmissionMode.cs | 25 +++ .../LiveTv/TunerHosts/SatIp/Utils.cs | 90 +++++++++ .../MediaBrowser.Server.Implementations.csproj | 14 ++ 16 files changed, 1222 insertions(+), 16 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs new file mode 100644 index 0000000000..dddd771790 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/ReportBlock.cs @@ -0,0 +1,79 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp +{ + public class ReportBlock + { + /// + /// Get the length of the block. + /// + public int BlockLength { get { return (24); } } + /// + /// Get the synchronization source. + /// + public string SynchronizationSource { get; private set; } + /// + /// Get the fraction lost. + /// + public int FractionLost { get; private set; } + /// + /// Get the cumulative packets lost. + /// + public int CumulativePacketsLost { get; private set; } + /// + /// Get the highest number received. + /// + public int HighestNumberReceived { get; private set; } + /// + /// Get the inter arrival jitter. + /// + public int InterArrivalJitter { get; private set; } + /// + /// Get the timestamp of the last report. + /// + public int LastReportTimeStamp { get; private set; } + /// + /// Get the delay since the last report. + /// + public int DelaySinceLastReport { get; private set; } + + /// + /// Initialize a new instance of the ReportBlock class. + /// + public ReportBlock() { } + + /// + /// Unpack the data in a packet. + /// + /// The buffer containing the packet. + /// The offset to the first byte of the packet within the buffer. + /// An ErrorSpec instance if an error occurs; null otherwise. + public void Process(byte[] buffer, int offset) + { + SynchronizationSource = Utils.ConvertBytesToString(buffer, offset, 4); + FractionLost = buffer[offset + 4]; + CumulativePacketsLost = Utils.Convert3BytesToInt(buffer, offset + 5); + HighestNumberReceived = Utils.Convert4BytesToInt(buffer, offset + 8); + InterArrivalJitter = Utils.Convert4BytesToInt(buffer, offset + 12); + LastReportTimeStamp = Utils.Convert4BytesToInt(buffer, offset + 16); + DelaySinceLastReport = Utils.Convert4BytesToInt(buffer, offset + 20); + + + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs new file mode 100644 index 0000000000..990b6dd949 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpAppPacket.cs @@ -0,0 +1,68 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ +using System.Text; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp +{ + class RtcpAppPacket : RtcpPacket + { + /// + /// Get the synchronization source. + /// + public int SynchronizationSource { get; private set; } + /// + /// Get the name. + /// + public string Name { get; private set; } + /// + /// Get the identity. + /// + public int Identity { get; private set; } + /// + /// Get the variable data portion. + /// + public string Data { get; private set; } + + public override void Parse(byte[] buffer, int offset) + { + base.Parse(buffer, offset); + SynchronizationSource = Utils.Convert4BytesToInt(buffer, offset + 4); + Name = Utils.ConvertBytesToString(buffer, offset + 8, 4); + Identity = Utils.Convert2BytesToInt(buffer, offset + 12); + + int dataLength = Utils.Convert2BytesToInt(buffer, offset + 14); + if (dataLength != 0) + Data = Utils.ConvertBytesToString(buffer, offset + 16, dataLength); + } + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("Application Specific.\n"); + sb.AppendFormat("Version : {0} .\n", Version); + sb.AppendFormat("Padding : {0} .\n", Padding); + sb.AppendFormat("Report Count : {0} .\n", ReportCount); + sb.AppendFormat("PacketType: {0} .\n", Type); + sb.AppendFormat("Length : {0} .\n", Length); + sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource); + sb.AppendFormat("Name : {0} .\n", Name); + sb.AppendFormat("Identity : {0} .\n", Identity); + sb.AppendFormat("Data : {0} .\n", Data); + sb.AppendFormat(".\n"); + return sb.ToString(); + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs new file mode 100644 index 0000000000..c79ea31a89 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpByePacket.cs @@ -0,0 +1,59 @@ +using System.Collections.ObjectModel; +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ +using System.Text; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp +{ + public class RtcpByePacket :RtcpPacket + { + public Collection SynchronizationSources { get; private set; } + public string ReasonForLeaving { get; private set; } + public override void Parse(byte[] buffer, int offset) + { + base.Parse(buffer, offset); + SynchronizationSources = new Collection(); + int index = 4; + + while (SynchronizationSources.Count < ReportCount) + { + SynchronizationSources.Add(Utils.ConvertBytesToString(buffer, offset + index, 4)); + index += 4; + } + + if (index < Length) + { + int reasonLength = buffer[offset + index]; + ReasonForLeaving = Utils.ConvertBytesToString(buffer, offset + index + 1, reasonLength); + } + } + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("ByeBye .\n"); + sb.AppendFormat("Version : {0} .\n", Version); + sb.AppendFormat("Padding : {0} .\n", Padding); + sb.AppendFormat("Report Count : {0} .\n", ReportCount); + sb.AppendFormat("PacketType: {0} .\n", Type); + sb.AppendFormat("Length : {0} .\n", Length); + sb.AppendFormat("SynchronizationSources : {0} .\n", SynchronizationSources); + sb.AppendFormat("ReasonForLeaving : {0} .\n", ReasonForLeaving); + sb.AppendFormat(".\n"); + return sb.ToString(); + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs new file mode 100644 index 0000000000..2c54f06654 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpListener.cs @@ -0,0 +1,203 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp +{ + public class RtcpListener + { + private readonly ILogger _logger; + private Thread _rtcpListenerThread; + private AutoResetEvent _rtcpListenerThreadStopEvent = null; + private UdpClient _udpClient; + private IPEndPoint _multicastEndPoint; + private IPEndPoint _serverEndPoint; + private TransmissionMode _transmissionMode; + + public RtcpListener(String address, int port, TransmissionMode mode,ILogger logger) + { + _logger = logger; + _transmissionMode = mode; + switch (mode) + { + case TransmissionMode.Unicast: + _udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(address), port)); + _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); + break; + case TransmissionMode.Multicast: + _multicastEndPoint = new IPEndPoint(IPAddress.Parse(address), port); + _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); + _udpClient = new UdpClient(); + _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); + _udpClient.ExclusiveAddressUse = false; + _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, port)); + _udpClient.JoinMulticastGroup(_multicastEndPoint.Address); + break; + } + //StartRtcpListenerThread(); + } + + public void StartRtcpListenerThread() + { + // Kill the existing thread if it is in "zombie" state. + if (_rtcpListenerThread != null && !_rtcpListenerThread.IsAlive) + { + StopRtcpListenerThread(); + } + + if (_rtcpListenerThread == null) + { + _logger.Info("SAT>IP : starting new RTCP listener thread"); + _rtcpListenerThreadStopEvent = new AutoResetEvent(false); + _rtcpListenerThread = new Thread(new ThreadStart(RtcpListenerThread)); + _rtcpListenerThread.Name = string.Format("SAT>IP tuner RTCP listener"); + _rtcpListenerThread.IsBackground = true; + _rtcpListenerThread.Priority = ThreadPriority.Lowest; + _rtcpListenerThread.Start(); + } + } + + public void StopRtcpListenerThread() + { + if (_rtcpListenerThread != null) + { + if (!_rtcpListenerThread.IsAlive) + { + _logger.Info("SAT>IP : aborting old RTCP listener thread"); + _rtcpListenerThread.Abort(); + } + else + { + _rtcpListenerThreadStopEvent.Set(); + if (!_rtcpListenerThread.Join(400 * 2)) + { + _logger.Info("SAT>IP : failed to join RTCP listener thread, aborting thread"); + _rtcpListenerThread.Abort(); + } + } + _rtcpListenerThread = null; + if (_rtcpListenerThreadStopEvent != null) + { + _rtcpListenerThreadStopEvent.Close(); + _rtcpListenerThreadStopEvent = null; + } + } + } + + private void RtcpListenerThread() + { + try + { + bool receivedGoodBye = false; + try + { + _udpClient.Client.ReceiveTimeout = 400; + IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Any, 0); + while (!receivedGoodBye && !_rtcpListenerThreadStopEvent.WaitOne(1)) + { + byte[] packets = _udpClient.Receive(ref serverEndPoint); + if (packets == null) + { + continue; + } + + int offset = 0; + while (offset < packets.Length) + { + switch (packets[offset + 1]) + { + case 200: //sr + var sr = new RtcpSenderReportPacket(); + sr.Parse(packets, offset); + offset += sr.Length; + break; + case 201: //rr + var rr = new RtcpReceiverReportPacket(); + rr.Parse(packets, offset); + offset += rr.Length; + break; + case 202: //sd + var sd = new RtcpSourceDescriptionPacket(); + sd.Parse(packets, offset); + offset += sd.Length; + break; + case 203: // bye + var bye = new RtcpByePacket(); + bye.Parse(packets, offset); + receivedGoodBye = true; + OnPacketReceived(new RtcpPacketReceivedArgs(bye)); + offset += bye.Length; + break; + case 204: // app + var app = new RtcpAppPacket(); + app.Parse(packets, offset); + OnPacketReceived(new RtcpPacketReceivedArgs(app)); + offset += app.Length; + break; + } + } + + } + } + finally + { + switch (_transmissionMode) + { + case TransmissionMode.Multicast: + _udpClient.DropMulticastGroup(_multicastEndPoint.Address); + _udpClient.Close(); + break; + case TransmissionMode.Unicast: + _udpClient.Close(); + break; + } + } + } + catch (ThreadAbortException) + { + } + catch (Exception ex) + { + _logger.Info(string.Format("SAT>IP : RTCP listener thread exception"), ex); + return; + } + _logger.Info("SAT>IP : RTCP listener thread stopping"); + } + public delegate void PacketReceivedHandler(object sender, RtcpPacketReceivedArgs e); + public event PacketReceivedHandler PacketReceived; + public class RtcpPacketReceivedArgs : EventArgs + { + public Object Packet { get; private set; } + + public RtcpPacketReceivedArgs(Object packet) + { + Packet = packet; + } + } + protected void OnPacketReceived(RtcpPacketReceivedArgs args) + { + if (PacketReceived != null) + { + PacketReceived(this, args); + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs new file mode 100644 index 0000000000..0a949eb7ed --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpPacket.cs @@ -0,0 +1,37 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp +{ + public abstract class RtcpPacket + { + public int Version { get; private set; } + public bool Padding { get; private set; } + public int ReportCount { get; private set; } + public int Type { get; private set; } + public int Length { get; private set; } + + public virtual void Parse(byte[] buffer, int offset) + { + Version = buffer[offset] >> 6; + Padding = (buffer[offset] & 0x20) != 0; + ReportCount = buffer[offset] & 0x1f; + Type = buffer[offset + 1]; + Length = (Utils.Convert2BytesToInt(buffer, offset + 2) * 4) + 4; + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs new file mode 100644 index 0000000000..abb8636522 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpReceiverReportPacket.cs @@ -0,0 +1,68 @@ +using System.Collections.ObjectModel; +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ +using System.Text; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp +{ + public class RtcpReceiverReportPacket :RtcpPacket + { + public string SynchronizationSource { get; private set; } + public Collection ReportBlocks { get; private set; } + public byte[] ProfileExtension { get; private set; } + public override void Parse(byte[] buffer, int offset) + { + base.Parse(buffer, offset); + SynchronizationSource = Utils.ConvertBytesToString(buffer, offset + 4, 4); + + ReportBlocks = new Collection(); + int index = 8; + + while (ReportBlocks.Count < ReportCount) + { + ReportBlock reportBlock = new ReportBlock(); + reportBlock.Process(buffer, offset + index); + ReportBlocks.Add(reportBlock); + index += reportBlock.BlockLength; + } + + if (index < Length) + { + ProfileExtension = new byte[Length - index]; + + for (int extensionIndex = 0; index < Length; index++) + { + ProfileExtension[extensionIndex] = buffer[offset + index]; + extensionIndex++; + } + } + } + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("Receiver Report.\n"); + sb.AppendFormat("Version : {0} .\n", Version); + sb.AppendFormat("Padding : {0} .\n", Padding); + sb.AppendFormat("Report Count : {0} .\n", ReportCount); + sb.AppendFormat("PacketType: {0} .\n", Type); + sb.AppendFormat("Length : {0} .\n", Length); + sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource); + sb.AppendFormat(".\n"); + return sb.ToString(); + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs new file mode 100644 index 0000000000..dda5d6a033 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSenderReportPacket.cs @@ -0,0 +1,105 @@ +using System.Collections.ObjectModel; +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ +using System.Text; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp +{ + public class RtcpSenderReportPacket : RtcpPacket + { + #region Properties + /// + /// Get the synchronization source. + /// + public int SynchronizationSource { get; private set; } + /// + /// Get the NPT timestamp. + /// + public long NPTTimeStamp { get; private set; } + /// + /// Get the RTP timestamp. + /// + public int RTPTimeStamp { get; private set; } + /// + /// Get the packet count. + /// + public int SenderPacketCount { get; private set; } + /// + /// Get the octet count. + /// + public int SenderOctetCount { get; private set; } + /// + /// Get the list of report blocks. + /// + public Collection ReportBlocks { get; private set; } + /// + /// Get the profile extension data. + /// + public byte[] ProfileExtension { get; private set; } + #endregion + + public override void Parse(byte[] buffer, int offset) + { + base.Parse(buffer, offset); + SynchronizationSource = Utils.Convert4BytesToInt(buffer, offset + 4); + NPTTimeStamp = Utils.Convert8BytesToLong(buffer, offset + 8); + RTPTimeStamp = Utils.Convert4BytesToInt(buffer, offset + 16); + SenderPacketCount = Utils.Convert4BytesToInt(buffer, offset + 20); + SenderOctetCount = Utils.Convert4BytesToInt(buffer, offset + 24); + + ReportBlocks = new Collection(); + int index = 28; + + while (ReportBlocks.Count < ReportCount) + { + ReportBlock reportBlock = new ReportBlock(); + reportBlock.Process(buffer, offset + index); + ReportBlocks.Add(reportBlock); + index += reportBlock.BlockLength; + } + + if (index < Length) + { + ProfileExtension = new byte[Length - index]; + + for (int extensionIndex = 0; index < Length; index++) + { + ProfileExtension[extensionIndex] = buffer[offset + index]; + extensionIndex++; + } + } + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("Sender Report.\n"); + sb.AppendFormat("Version : {0} .\n", Version); + sb.AppendFormat("Padding : {0} .\n", Padding); + sb.AppendFormat("Report Count : {0} .\n", ReportCount); + sb.AppendFormat("PacketType: {0} .\n", Type); + sb.AppendFormat("Length : {0} .\n", Length); + sb.AppendFormat("SynchronizationSource : {0} .\n", SynchronizationSource); + sb.AppendFormat("NTP Timestamp : {0} .\n", Utils.NptTimestampToDateTime(NPTTimeStamp)); + sb.AppendFormat("RTP Timestamp : {0} .\n", RTPTimeStamp); + sb.AppendFormat("Sender PacketCount : {0} .\n", SenderPacketCount); + sb.AppendFormat("Sender Octet Count : {0} .\n", SenderOctetCount); + sb.AppendFormat(".\n"); + return sb.ToString(); + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs new file mode 100644 index 0000000000..0a95a44133 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/RtcpSourceDescriptionPacket.cs @@ -0,0 +1,57 @@ +using System.Collections.ObjectModel; +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ +using System.Text; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp +{ + class RtcpSourceDescriptionPacket :RtcpPacket + { /// + /// Get the list of source descriptions. + /// + public Collection Descriptions; + public override void Parse(byte[] buffer, int offset) + { + base.Parse(buffer, offset); + Descriptions = new Collection(); + + int index = 4; + + while (Descriptions.Count < ReportCount) + { + SourceDescriptionBlock descriptionBlock = new SourceDescriptionBlock(); + descriptionBlock.Process(buffer, offset + index); + Descriptions.Add(descriptionBlock); + index += descriptionBlock.BlockLength; + } + } + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("Source Description.\n"); + sb.AppendFormat("Version : {0} .\n", Version); + sb.AppendFormat("Padding : {0} .\n", Padding); + sb.AppendFormat("Report Count : {0} .\n", ReportCount); + sb.AppendFormat("PacketType: {0} .\n", Type); + sb.AppendFormat("Length : {0} .\n", Length); + sb.AppendFormat("Descriptions : {0} .\n", Descriptions); + + sb.AppendFormat(".\n"); + return sb.ToString(); + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs new file mode 100644 index 0000000000..bf56087cd8 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionBlock.cs @@ -0,0 +1,65 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ +using System.Collections.ObjectModel; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp +{ + class SourceDescriptionBlock + { + /// + /// Get the length of the block. + /// + public int BlockLength { get { return (blockLength + (blockLength % 4)); } } + + /// + /// Get the synchronization source. + /// + public string SynchronizationSource { get; private set; } + /// + /// Get the list of source descriptioni items. + /// + public Collection Items; + + private int blockLength; + + public void Process(byte[] buffer, int offset) + { + SynchronizationSource = Utils.ConvertBytesToString(buffer, offset, 4); + Items = new Collection(); + int index = 4; + bool done = false; + do + { + SourceDescriptionItem item = new SourceDescriptionItem(); + item.Process(buffer, offset + index); + + if (item.Type != 0) + { + Items.Add(item); + index += item.ItemLength; + blockLength += item.ItemLength; + } + else + { + blockLength++; + done = true; + } + } + while (!done); + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs new file mode 100644 index 0000000000..5dd0336421 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtcp/SourceDescriptionItem.cs @@ -0,0 +1,60 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtcp +{ + /// + /// The class that describes a source description item. + /// + public class SourceDescriptionItem + { + /// + /// Get the type. + /// + public int Type { get; private set; } + /// + /// Get the text. + /// + public string Text { get; private set; } + + /// + /// Get the length of the item. + /// + public int ItemLength { get { return (Text.Length + 2); } } + + /// + /// Initialize a new instance of the SourceDescriptionItem class. + /// + public SourceDescriptionItem() { } + + /// + /// Unpack the data in a packet. + /// + /// The buffer containing the packet. + /// The offset to the first byte of the packet within the buffer. + /// An ErrorSpec instance if an error occurs; null otherwise. + public void Process(byte[] buffer, int offset) + { + Type = buffer[offset]; + if (Type != 0) + { + int length = buffer[offset + 1]; + Text = Utils.ConvertBytesToString(buffer, offset + 2, length); + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs new file mode 100644 index 0000000000..ea6a9ba6aa --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpListener.cs @@ -0,0 +1,160 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtp +{ + public class RtpListener + { + private readonly ILogger _logger; + private AutoResetEvent _rtpListenerThreadStopEvent; + private Thread _rtpListenerThread; + private UdpClient _udpClient; + private IPEndPoint _multicastEndPoint; + private IPEndPoint _serverEndPoint; + private TransmissionMode _transmissionMode; + public RtpListener(String address, int port,TransmissionMode mode,ILogger logger) + { + _logger = logger; + _transmissionMode = mode; + switch (mode) + { + case TransmissionMode.Unicast: + _udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(address), port)); + _serverEndPoint = new IPEndPoint(IPAddress.Any, 0); + break; + case TransmissionMode.Multicast: + _multicastEndPoint = new IPEndPoint(IPAddress.Parse(address), port); + _serverEndPoint = null; + _udpClient = new UdpClient(); + _udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); + _udpClient.ExclusiveAddressUse = false; + _udpClient.Client.Bind(new IPEndPoint(IPAddress.Any, _multicastEndPoint.Port)); + _udpClient.JoinMulticastGroup(_multicastEndPoint.Address); + break; + } + //StartRtpListenerThread(); + } + public void StartRtpListenerThread() + { + // Kill the existing thread if it is in "zombie" state. + if (_rtpListenerThread != null && !_rtpListenerThread.IsAlive) + { + StopRtpListenerThread(); + } + + if (_rtpListenerThread == null) + { + _logger.Info("SAT>IP : starting new RTP listener thread"); + _rtpListenerThreadStopEvent = new AutoResetEvent(false); + _rtpListenerThread = new Thread(new ThreadStart(RtpListenerThread)); + _rtpListenerThread.Name = string.Format("SAT>IP tuner RTP listener"); + _rtpListenerThread.IsBackground = true; + _rtpListenerThread.Priority = ThreadPriority.Lowest; + _rtpListenerThread.Start(); + } + } + + public void StopRtpListenerThread() + { + if (_rtpListenerThread != null) + { + if (!_rtpListenerThread.IsAlive) + { + _logger.Info("SAT>IP : aborting old RTP listener thread"); + _rtpListenerThread.Abort(); + } + else + { + _rtpListenerThreadStopEvent.Set(); + if (!_rtpListenerThread.Join(400 * 2)) + { + _logger.Info("SAT>IP : failed to join RTP listener thread, aborting thread"); + _rtpListenerThread.Abort(); + } + } + _rtpListenerThread = null; + if (_rtpListenerThreadStopEvent != null) + { + _rtpListenerThreadStopEvent.Close(); + _rtpListenerThreadStopEvent = null; + } + } + } + + private void RtpListenerThread() + { + try + { + try + { + + while (!_rtpListenerThreadStopEvent.WaitOne(1)) + { + byte[] receivedbytes = _udpClient.Receive(ref _serverEndPoint); + RtpPacket packet = RtpPacket.Decode(receivedbytes); + OnPacketReceived(new RtpPacketReceivedArgs(packet)); + } + } + finally + { + switch (_transmissionMode) + { + case TransmissionMode.Multicast: + _udpClient.DropMulticastGroup(_multicastEndPoint.Address); + _udpClient.Close(); + break; + case TransmissionMode.Unicast: + _udpClient.Close(); + break; + } + } + } + catch (ThreadAbortException) + { + } + catch (Exception ex) + { + _logger.Info(string.Format("SAT>IP : RTP listener thread exception"), ex); + return; + } + _logger.Info("SAT>IP : RTP listener thread stopping"); + } + public delegate void PacketReceivedHandler(object sender, RtpPacketReceivedArgs e); + public event PacketReceivedHandler PacketReceived; + public class RtpPacketReceivedArgs : EventArgs + { + public RtpPacket Packet { get; private set; } + + public RtpPacketReceivedArgs(RtpPacket packet) + { + Packet = packet; + } + } + protected void OnPacketReceived(RtpPacketReceivedArgs args) + { + if (PacketReceived != null) + { + PacketReceived(this, args); + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs new file mode 100644 index 0000000000..489d7f087c --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtp/RtpPacket.cs @@ -0,0 +1,116 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System; +using System.Collections.ObjectModel; +using System.Text; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtp +{ + public class RtpPacket + { + private static int MinHeaderLength = 12; + public int HeaderSize = MinHeaderLength; + public int Version { get; set; } + public Boolean Padding { get; set; } + public Boolean Extension { get; set; } + public int ContributingSourceCount { get; set; } + public Boolean Marker { get; set; } + public int PayloadType { get; set; } + public int SequenceNumber { get; set; } + public long TimeStamp { get; set; } + public long SynchronizationSource { get; set; } + public Collection ContributingSources { get; private set; } + public int ExtensionHeaderId = 0; + public int ExtensionHeaderLength = 0; + public bool HasPayload { get; set; } + public byte[] Payload { get; set; } + public RtpPacket() + { + + } + public static RtpPacket Decode(byte[] buffer) + { + var packet = new RtpPacket(); + packet.Version = buffer[0] >> 6; + packet.Padding = (buffer[0] & 0x20) != 0; + packet.Extension = (buffer[0] & 0x10) != 0; + packet.ContributingSourceCount = buffer[0] & 0x0f; + + packet.Marker = (buffer[1] & 0x80) != 0; + packet.PayloadType = buffer[1] & 0x7f; + + packet.SequenceNumber = Utils.Convert2BytesToInt(buffer, 2); + packet.TimeStamp = Utils.Convert4BytesToLong(buffer, 4); + packet.SynchronizationSource = Utils.Convert4BytesToLong(buffer, 8); + + int index = 12; + + if (packet.ContributingSourceCount != 0) + { + packet.ContributingSources = new Collection(); + + while (packet.ContributingSources.Count < packet.ContributingSourceCount) + { + packet.ContributingSources.Add(Utils.ConvertBytesToString(buffer, index, 4)); + index += 4; + } + } + var dataoffset = 0; + if (!packet.Extension) + dataoffset = index; + else + { + packet.ExtensionHeaderId = Utils.Convert2BytesToInt(buffer, index); + packet.ExtensionHeaderLength = Utils.Convert2BytesToInt(buffer, index + 2); + dataoffset = index + packet.ExtensionHeaderLength + 4; + } + + var dataLength = buffer.Length - dataoffset; + if (dataLength > dataoffset) + { + packet.HasPayload = true; + packet.Payload = new byte[dataLength]; + Array.Copy(buffer, dataoffset, packet.Payload, 0, dataLength); + } + else + { + packet.HasPayload = false; + } + return packet; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("RTP Packet"); + sb.AppendFormat("Version: {0} \n", Version); + sb.AppendFormat("Padding: {0} \n", Padding); + sb.AppendFormat("Extension: {0} \n", Extension); + sb.AppendFormat("Contributing Source Identifiers Count: {0} \n", ContributingSourceCount); + sb.AppendFormat("Marker: {0} \n", Marker); + sb.AppendFormat("Payload Type: {0} \n", PayloadType); + sb.AppendFormat("Sequence Number: {0} \n", SequenceNumber); + sb.AppendFormat("Timestamp: {0} .\n", TimeStamp); + sb.AppendFormat("Synchronization Source Identifier: {0} \n", SynchronizationSource); + sb.AppendFormat("\n"); + return sb.ToString(); + } + + } + +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs index ba5c604ed0..cb0e573da2 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs @@ -237,7 +237,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp string modelurl = ""; string serialnumber = ""; string presentationurl = ""; - string capabilities = ""; + //string capabilities = ""; string m3u = ""; var document = XDocument.Load(locationUri.AbsoluteUri); var xnm = new XmlNamespaceManager(new NameTable()); @@ -284,20 +284,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp var capabilitiesElement = deviceElement.Element(n1 + "X_SATIPCAP"); if (capabilitiesElement != null) { - //_capabilities = capabilitiesElement.Value; - //if (capabilitiesElement.Value.Contains(',')) - //{ - // string[] capabilities = capabilitiesElement.Value.Split(','); - // foreach (var capability in capabilities) - // { - // ReadCapability(capability); - // } - //} - //else - //{ - // ReadCapability(capabilitiesElement.Value); - //} + //_capabilities = capabilitiesElement.Value; + if (capabilitiesElement.Value.Contains(',')) + { + string[] capabilities = capabilitiesElement.Value.Split(','); + foreach (var capability in capabilities) + { + ReadCapability(capability); + } } + else + { + ReadCapability(capabilitiesElement.Value); + } + } else { _supportsDVBS = true; @@ -314,8 +314,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp Id = uniquedevicename, IsEnabled = true, Type = SatIpHost.DeviceType, - Tuners = 1, - TunersAvailable = 1, + Tuners = _tunerCountDVBS, + TunersAvailable = _tunerCountDVBS, M3UUrl = m3u }; diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs new file mode 100644 index 0000000000..71d7656d95 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/TransmissionMode.cs @@ -0,0 +1,25 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp +{ + public enum TransmissionMode + { + Unicast, + Multicast + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs new file mode 100644 index 0000000000..3595e4b0ad --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Utils.cs @@ -0,0 +1,90 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ +using System; +using System.Text; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp +{ + public class Utils + { + public static int Convert2BytesToInt(byte[] buffer, int offset) + { + int temp = (int)buffer[offset]; + temp = (temp * 256) + buffer[offset + 1]; + + return (temp); + } + public static int Convert3BytesToInt(byte[] buffer, int offset) + { + int temp = (int)buffer[offset]; + temp = (temp * 256) + buffer[offset + 1]; + temp = (temp * 256) + buffer[offset + 2]; + + return (temp); + } + public static int Convert4BytesToInt(byte[] buffer, int offset) + { + int temp =(int)buffer[offset]; + temp = (temp * 256) + buffer[offset + 1]; + temp = (temp * 256) + buffer[offset + 2]; + temp = (temp * 256) + buffer[offset + 3]; + + return (temp); + } + public static long Convert4BytesToLong(byte[] buffer, int offset) + { + long temp = 0; + + for (int index = 0; index < 4; index++) + temp = (temp * 256) + buffer[offset + index]; + + return (temp); + } + public static long Convert8BytesToLong(byte[] buffer, int offset) + { + long temp = 0; + + for (int index = 0; index < 8; index++) + temp = (temp * 256) + buffer[offset + index]; + + return (temp); + } + public static string ConvertBytesToString(byte[] buffer, int offset, int length) + { + StringBuilder reply = new StringBuilder(4); + for (int index = 0; index < length; index++) + reply.Append((char)buffer[offset + index]); + return (reply.ToString()); + } + public static DateTime NptTimestampToDateTime(long nptTimestamp) { return NptTimestampToDateTime((uint)((nptTimestamp >> 32) & 0xFFFFFFFF), (uint)(nptTimestamp & 0xFFFFFFFF),null); } + + public static DateTime NptTimestampToDateTime(uint seconds, uint fractions, DateTime? epoch ) + { + ulong ticks =(ulong)((seconds * TimeSpan.TicksPerSecond) + ((fractions * TimeSpan.TicksPerSecond) / 0x100000000L)); + if (epoch.HasValue) return epoch.Value + TimeSpan.FromTicks((Int64)ticks); + return (seconds & 0x80000000L) == 0 ? UtcEpoch2036 + TimeSpan.FromTicks((Int64)ticks) : UtcEpoch1900 + TimeSpan.FromTicks((Int64)ticks); + } + + //When the First Epoch will wrap (The real Y2k) + public static DateTime UtcEpoch2036 = new DateTime(2036, 2, 7, 6, 28, 16, DateTimeKind.Utc); + + public static DateTime UtcEpoch1900 = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + public static DateTime UtcEpoch1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 6879c3f407..9a92cf896a 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -251,6 +251,18 @@ + + + + + + + + + + + + @@ -258,6 +270,8 @@ + + -- cgit v1.2.3 From cc7b150b90e238286121d58e618d4f8f7c2b6c49 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 5 Sep 2016 01:39:14 -0400 Subject: update recording layout --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 7 +++- MediaBrowser.Api/Playback/BaseStreamingService.cs | 12 +++++- MediaBrowser.Api/Playback/StreamState.cs | 2 + MediaBrowser.Model/LiveTv/RecordingQuery.cs | 2 + MediaBrowser.Model/System/SystemInfo.cs | 2 + .../LiveTv/LiveTvManager.cs | 48 ++++++++++++++++++++-- .../ApplicationHost.cs | 3 +- .../Migrations/UpdateLevelMigration.cs | 44 +++++++++++++++----- 8 files changed, 103 insertions(+), 17 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 545ac162ff..f6817e0e7b 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -155,6 +155,9 @@ namespace MediaBrowser.Api.LiveTv [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] public bool? EnableUserData { get; set; } + public bool? IsMovie { get; set; } + public bool? IsSeries { get; set; } + public GetRecordings() { EnableTotalRecordCount = true; @@ -863,7 +866,9 @@ namespace MediaBrowser.Api.LiveTv Status = request.Status, SeriesTimerId = request.SeriesTimerId, IsInProgress = request.IsInProgress, - EnableTotalRecordCount = request.EnableTotalRecordCount + EnableTotalRecordCount = request.EnableTotalRecordCount, + IsMovie = request.IsMovie, + IsSeries = request.IsSeries }, options, CancellationToken.None).ConfigureAwait(false); diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index e626d49f42..b419250f71 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1786,6 +1786,16 @@ namespace MediaBrowser.Api.Playback // state.SegmentLength = 6; //} + if (state.VideoRequest != null) + { + if (!string.IsNullOrWhiteSpace(state.VideoRequest.VideoCodec)) + { + state.SupportedVideoCodecs = state.VideoRequest.VideoCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); + state.VideoRequest.VideoCodec = state.SupportedVideoCodecs.FirstOrDefault(i => MediaEncoder.CanEncodeToAudioCodec(i)) + ?? state.SupportedVideoCodecs.FirstOrDefault(); + } + } + if (!string.IsNullOrWhiteSpace(request.AudioCodec)) { state.SupportedAudioCodecs = request.AudioCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); @@ -2028,7 +2038,7 @@ namespace MediaBrowser.Api.Playback } // Source and target codecs must match - if (!string.Equals(request.VideoCodec, videoStream.Codec, StringComparison.OrdinalIgnoreCase)) + if (string.IsNullOrEmpty(videoStream.Codec) || !state.SupportedVideoCodecs.Contains(videoStream.Codec, StringComparer.OrdinalIgnoreCase)) { return false; } diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index d7d94c69b4..2e92c4a499 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -112,6 +112,7 @@ namespace MediaBrowser.Api.Playback public string OutputVideoSync = "-1"; public List SupportedAudioCodecs { get; set; } + public List SupportedVideoCodecs { get; set; } public string UserAgent { get; set; } public StreamState(IMediaSourceManager mediaSourceManager, ILogger logger) @@ -119,6 +120,7 @@ namespace MediaBrowser.Api.Playback _mediaSourceManager = mediaSourceManager; _logger = logger; SupportedAudioCodecs = new List(); + SupportedVideoCodecs = new List(); PlayableStreamFileNames = new List(); RemoteHttpHeaders = new Dictionary(StringComparer.OrdinalIgnoreCase); } diff --git a/MediaBrowser.Model/LiveTv/RecordingQuery.cs b/MediaBrowser.Model/LiveTv/RecordingQuery.cs index 923d303f80..cedc0b8525 100644 --- a/MediaBrowser.Model/LiveTv/RecordingQuery.cs +++ b/MediaBrowser.Model/LiveTv/RecordingQuery.cs @@ -68,6 +68,8 @@ namespace MediaBrowser.Model.LiveTv /// The fields. public ItemFields[] Fields { get; set; } public bool? EnableImages { get; set; } + public bool? IsMovie { get; set; } + public bool? IsSeries { get; set; } public int? ImageTypeLimit { get; set; } public ImageType[] EnableImageTypes { get; set; } diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 3d1de5b379..c4d056a612 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -8,6 +8,8 @@ namespace MediaBrowser.Model.System /// public class SystemInfo : PublicSystemInfo { + public PackageVersionClass SystemUpdateLevel { get; set; } + /// /// Gets or sets the display name of the operating system. /// diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 88017aa59d..3d9a0f80ed 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -31,6 +31,8 @@ using CommonIO; using IniParser; using IniParser.Model; using MediaBrowser.Common.Events; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Events; namespace MediaBrowser.Server.Implementations.LiveTv @@ -1423,6 +1425,32 @@ namespace MediaBrowser.Server.Implementations.LiveTv return new QueryResult(); } + var includeItemTypes = new List(); + var excludeItemTypes = new List(); + + if (query.IsMovie.HasValue) + { + if (query.IsMovie.Value) + { + includeItemTypes.Add(typeof (Movie).Name); + } + else + { + excludeItemTypes.Add(typeof(Movie).Name); + } + } + if (query.IsSeries.HasValue) + { + if (query.IsSeries.Value) + { + includeItemTypes.Add(typeof(Episode).Name); + } + else + { + excludeItemTypes.Add(typeof(Episode).Name); + } + } + return _libraryManager.GetItemsResult(new InternalItemsQuery(user) { MediaTypes = new[] { MediaType.Video }, @@ -1433,7 +1461,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv Limit = Math.Min(200, query.Limit ?? int.MaxValue), SortBy = new[] { ItemSortBy.DateCreated }, SortOrder = SortOrder.Descending, - EnableTotalRecordCount = query.EnableTotalRecordCount + EnableTotalRecordCount = query.EnableTotalRecordCount, + IncludeItemTypes = includeItemTypes.ToArray(), + ExcludeItemTypes = excludeItemTypes.ToArray() }); } @@ -1492,6 +1522,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv recordings = recordings.Where(i => i.Status == val); } + if (query.IsMovie.HasValue) + { + var val = query.IsMovie.Value; + recordings = recordings.Where(i => i.IsMovie == val); + } + + if (query.IsSeries.HasValue) + { + var val = query.IsSeries.Value; + recordings = recordings.Where(i => i.IsSeries == val); + } + if (!string.IsNullOrEmpty(query.SeriesTimerId)) { var guid = new Guid(query.SeriesTimerId); @@ -1950,16 +1992,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv dto.Number = channel.Number; dto.ChannelNumber = channel.Number; dto.ChannelType = channel.ChannelType; - dto.ServiceName = GetService(channel).Name; + dto.ServiceName = channel.ServiceName; if (options.Fields.Contains(ItemFields.MediaSources)) { dto.MediaSources = channel.GetMediaSources(true).ToList(); } - var channelIdString = channel.Id.ToString("N"); if (options.AddCurrentProgram) { + var channelIdString = channel.Id.ToString("N"); var currentProgram = programs.FirstOrDefault(i => string.Equals(i.ChannelId, channelIdString)); if (currentProgram != null) diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index a25bd38123..86c5c06bc2 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -1096,7 +1096,8 @@ namespace MediaBrowser.Server.Startup.Common LocalAddress = localAddress, SupportsLibraryMonitor = SupportsLibraryMonitor, EncoderLocationType = MediaEncoder.EncoderLocationType, - SystemArchitecture = NativeApp.Environment.SystemArchitecture + SystemArchitecture = NativeApp.Environment.SystemArchitecture, + SystemUpdateLevel = ConfigurationManager.CommonConfiguration.SystemUpdateLevel }; } diff --git a/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs index 1c90a74386..de898e66cb 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Implementations.Updates; @@ -55,21 +56,39 @@ namespace MediaBrowser.Server.Startup.Common.Migrations } } - private async Task CheckVersion(Version currentVersion, PackageVersionClass updateLevel, CancellationToken cancellationToken) + private async Task CheckVersion(Version currentVersion, PackageVersionClass currentUpdateLevel, CancellationToken cancellationToken) { var releases = await new GithubUpdater(_httpClient, _jsonSerializer, TimeSpan.FromMinutes(3)) .GetLatestReleases("MediaBrowser", "Emby", _releaseAssetFilename, cancellationToken).ConfigureAwait(false); - var newUpdateLevel = updateLevel; + var newUpdateLevel = GetNewUpdateLevel(currentVersion, currentUpdateLevel, releases); + + if (newUpdateLevel != currentUpdateLevel) + { + _config.Configuration.SystemUpdateLevel = newUpdateLevel; + _config.SaveConfiguration(); + } + } + + private PackageVersionClass GetNewUpdateLevel(Version currentVersion, PackageVersionClass currentUpdateLevel, List releases) + { + var newUpdateLevel = currentUpdateLevel; // If the current version is later than current stable, set the update level to beta if (releases.Count >= 1) { var release = releases[0]; var version = ParseVersion(release.tag_name); - if (version != null && currentVersion > version) + if (version != null) { - newUpdateLevel = PackageVersionClass.Beta; + if (currentVersion > version) + { + newUpdateLevel = PackageVersionClass.Beta; + } + else + { + return PackageVersionClass.Release; + } } } @@ -78,17 +97,20 @@ namespace MediaBrowser.Server.Startup.Common.Migrations { var release = releases[1]; var version = ParseVersion(release.tag_name); - if (version != null && currentVersion > version) + if (version != null) { - newUpdateLevel = PackageVersionClass.Dev; + if (currentVersion > version) + { + newUpdateLevel = PackageVersionClass.Dev; + } + else + { + return PackageVersionClass.Beta; + } } } - if (newUpdateLevel != updateLevel) - { - _config.Configuration.SystemUpdateLevel = newUpdateLevel; - _config.SaveConfiguration(); - } + return newUpdateLevel; } private Version ParseVersion(string versionString) -- cgit v1.2.3 From d4324b7e893725c1fc42eb482d54184420b9a5d9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 5 Sep 2016 16:07:36 -0400 Subject: add chapter image error handling --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 3 +- .../Collections/ManualCollectionsFolder.cs | 36 +++++++++++++ MediaBrowser.Controller/Entities/UserView.cs | 3 +- .../MediaBrowser.Controller.csproj | 1 + .../Providers/BaseItemXmlParser.cs | 27 ++++++---- .../Folders/CollectionFolderMetadataService.cs | 14 +++++ .../Collections/CollectionsDynamicFolder.cs | 1 + .../Collections/ManualCollectionsFolder.cs | 36 ------------- .../LiveTv/EmbyTV/EncodedRecorder.cs | 22 +++++++- .../MediaBrowser.Server.Implementations.csproj | 1 - .../MediaEncoder/EncodingManager.cs | 16 +++--- .../UserViews/CollectionFolderImageProvider.cs | 62 ++++++++++++++++++++++ .../MediaBrowser.WebDashboard.csproj | 6 --- 13 files changed, 160 insertions(+), 68 deletions(-) create mode 100644 MediaBrowser.Controller/Collections/ManualCollectionsFolder.cs delete mode 100644 MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index b419250f71..a979848e27 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1791,8 +1791,7 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrWhiteSpace(state.VideoRequest.VideoCodec)) { state.SupportedVideoCodecs = state.VideoRequest.VideoCodec.Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - state.VideoRequest.VideoCodec = state.SupportedVideoCodecs.FirstOrDefault(i => MediaEncoder.CanEncodeToAudioCodec(i)) - ?? state.SupportedVideoCodecs.FirstOrDefault(); + state.VideoRequest.VideoCodec = state.SupportedVideoCodecs.FirstOrDefault(); } } diff --git a/MediaBrowser.Controller/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Controller/Collections/ManualCollectionsFolder.cs new file mode 100644 index 0000000000..d2d28e5047 --- /dev/null +++ b/MediaBrowser.Controller/Collections/ManualCollectionsFolder.cs @@ -0,0 +1,36 @@ +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Collections +{ + public class ManualCollectionsFolder : BasePluginFolder, IHiddenFromDisplay + { + public ManualCollectionsFolder() + { + Name = "Collections"; + DisplayMediaType = "CollectionFolder"; + } + + public override bool IsHidden + { + get + { + return true; + } + } + + public bool IsHiddenFromUser(User user) + { + return !ConfigurationManager.Configuration.DisplayCollectionsView; + } + + public override string CollectionType + { + get { return Model.Entities.CollectionType.BoxSets; } + } + + public override string GetClientTypeName() + { + return typeof(CollectionFolder).Name; + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 194ba0ee48..35375e7e66 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -113,8 +113,7 @@ namespace MediaBrowser.Controller.Entities { var standaloneTypes = new List { - CollectionType.Playlists, - CollectionType.BoxSets + CollectionType.Playlists }; var collectionFolder = folder as ICollectionFolder; diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index e7eaa1dc0b..5e74a39994 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -98,6 +98,7 @@ + diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index 4484adb1db..fccbd9211f 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -790,20 +790,25 @@ namespace MediaBrowser.Controller.Providers } default: - if (_validProviderIds.ContainsKey(reader.Name)) - { - var id = reader.ReadElementContentAsString(); - if (!string.IsNullOrWhiteSpace(id)) + { + string readerName = reader.Name; + string providerIdValue; + if (_validProviderIds.TryGetValue(readerName, out providerIdValue)) { - item.SetProviderId(_validProviderIds[reader.Name], id); + var id = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(id)) + { + item.SetProviderId(providerIdValue, id); + } + } + else + { + reader.Skip(); } - } - else - { - reader.Skip(); - } - break; + break; + + } } } diff --git a/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs b/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs index cdaa383667..2f534c12e5 100644 --- a/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs +++ b/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using CommonIO; +using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -21,4 +22,17 @@ namespace MediaBrowser.Providers.Folders { } } + + public class ManualCollectionsFolderMetadataService : MetadataService + { + protected override void MergeData(MetadataResult source, MetadataResult target, List lockedFields, bool replaceData, bool mergeMetadataSettings) + { + ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); + } + + public ManualCollectionsFolderMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, fileSystem, userDataManager, libraryManager) + { + } + } + } diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs b/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs index 6cd9e96205..50bb6c5592 100644 --- a/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs +++ b/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Entities; using System.IO; using CommonIO; +using MediaBrowser.Controller.Collections; namespace MediaBrowser.Server.Implementations.Collections { diff --git a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs deleted file mode 100644 index 3e33066ae6..0000000000 --- a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs +++ /dev/null @@ -1,36 +0,0 @@ -using MediaBrowser.Controller.Entities; - -namespace MediaBrowser.Server.Implementations.Collections -{ - public class ManualCollectionsFolder : BasePluginFolder, IHiddenFromDisplay - { - public ManualCollectionsFolder() - { - Name = "Collections"; - DisplayMediaType = "CollectionFolder"; - } - - public override bool IsHidden - { - get - { - return true; - } - } - - public bool IsHiddenFromUser(User user) - { - return !ConfigurationManager.Configuration.DisplayCollectionsView; - } - - public override string CollectionType - { - get { return Model.Entities.CollectionType.BoxSets; } - } - - public override string GetClientTypeName() - { - return typeof(CollectionFolder).Name; - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index fc3a507d17..5e7e3a94f7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -53,11 +53,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { + if (mediaSource.Path.IndexOf("m3u8", StringComparison.OrdinalIgnoreCase) != -1) + { + await RecordWithoutTempFile(mediaSource, targetFile, duration, onStarted, cancellationToken) + .ConfigureAwait(false); + + return; + } + var tempfile = Path.Combine(_appPaths.TranscodingTempPath, Guid.NewGuid().ToString("N") + ".ts"); try { - await RecordInternal(mediaSource, tempfile, targetFile, duration, onStarted, cancellationToken) + await RecordWithTempFile(mediaSource, tempfile, targetFile, duration, onStarted, cancellationToken) .ConfigureAwait(false); } finally @@ -73,7 +81,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV } } - public async Task RecordInternal(MediaSourceInfo mediaSource, string tempFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) + private async Task RecordWithoutTempFile(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) + { + var durationToken = new CancellationTokenSource(duration); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + + await RecordFromFile(mediaSource, mediaSource.Path, targetFile, duration, onStarted, cancellationToken).ConfigureAwait(false); + + _logger.Info("Recording completed to file {0}", targetFile); + } + + private async Task RecordWithTempFile(MediaSourceInfo mediaSource, string tempFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { var httpRequestOptions = new HttpRequestOptions() { diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 9a92cf896a..8850f3d359 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -124,7 +124,6 @@ - diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs index 11338df6db..7d0841fa64 100644 --- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -149,16 +149,16 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder } } - // Add some time for the first chapter to make sure we don't end up with a black image - var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); + try + { + // Add some time for the first chapter to make sure we don't end up with a black image + var time = chapter.StartPositionTicks == 0 ? TimeSpan.FromTicks(Math.Min(FirstChapterTicks, video.RunTimeTicks ?? 0)) : TimeSpan.FromTicks(chapter.StartPositionTicks); - var protocol = MediaProtocol.File; + var protocol = MediaProtocol.File; - var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames); + var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, video.Path, protocol, null, video.PlayableStreamFileNames); - try - { - _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); var tempFile = await _encoder.ExtractVideoImage(inputPath, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false); File.Copy(tempFile, path, true); @@ -178,7 +178,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder } catch (Exception ex) { - _logger.ErrorException("Error extracting chapter images for {0}", ex, string.Join(",", inputPath)); + _logger.ErrorException("Error extracting chapter images for {0}", ex, string.Join(",", video.Path)); success = false; break; } diff --git a/MediaBrowser.Server.Implementations/UserViews/CollectionFolderImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/CollectionFolderImageProvider.cs index 29716d33e4..2cff4a14f0 100644 --- a/MediaBrowser.Server.Implementations/UserViews/CollectionFolderImageProvider.cs +++ b/MediaBrowser.Server.Implementations/UserViews/CollectionFolderImageProvider.cs @@ -13,6 +13,10 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Controller.Collections; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Querying; namespace MediaBrowser.Server.Implementations.UserViews { @@ -109,4 +113,62 @@ namespace MediaBrowser.Server.Implementations.UserViews return await base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex).ConfigureAwait(false); } } + + public class ManualCollectionFolderImageProvider : BaseDynamicImageProvider + { + private readonly ILibraryManager _libraryManager; + + public ManualCollectionFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) + { + _libraryManager = libraryManager; + } + + public override IEnumerable GetSupportedImages(IHasImages item) + { + return new List + { + ImageType.Primary + }; + } + + protected override async Task> GetItemsWithImages(IHasImages item) + { + var view = (ManualCollectionsFolder)item; + + var recursive = !new[] { CollectionType.Playlists, CollectionType.Channels }.Contains(view.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + + var items = _libraryManager.GetItemList(new InternalItemsQuery + { + Recursive = recursive, + IncludeItemTypes = new[] { typeof(BoxSet).Name }, + Limit = 20, + SortBy = new[] { ItemSortBy.Random } + }); + + return GetFinalItems(items.Where(i => i.HasImage(ImageType.Primary) || i.HasImage(ImageType.Thumb)).ToList(), 8); + } + + protected override bool Supports(IHasImages item) + { + return item is ManualCollectionsFolder; + } + + protected override async Task CreateImage(IHasImages item, List itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) + { + var outputPath = Path.ChangeExtension(outputPathWithoutExtension, ".png"); + + if (imageType == ImageType.Primary) + { + if (itemsWithImages.Count == 0) + { + return null; + } + + return await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540).ConfigureAwait(false); + } + + return await base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex).ConfigureAwait(false); + } + } + } diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index d1308a5013..2b828b8fcf 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -755,9 +755,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -944,9 +941,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest -- cgit v1.2.3 From 67505e24bdccae33387e59358c01471dd9536d42 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 6 Sep 2016 01:02:05 -0400 Subject: fix artist editor --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 8 +--- MediaBrowser.Controller/Library/NameExtensions.cs | 4 +- .../LiveTv/IHasRegistrationInfo.cs | 15 ------ MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 4 +- .../MediaBrowser.Controller.csproj | 1 - .../Configuration/ServerConfiguration.cs | 2 +- .../Music/AudioMetadataService.cs | 3 +- .../Dto/DtoService.cs | 20 ++++++++ .../LiveTv/EmbyTV/EmbyTV.cs | 26 ++-------- .../LiveTv/LiveTvManager.cs | 40 +++++++--------- MediaBrowser.Server.Mono/Native/BaseMonoApp.cs | 5 ++ .../ApplicationHost.cs | 16 ++++++- MediaBrowser.Server.Startup.Common/INativeApp.cs | 2 + .../Native/RegisterServer.bat | 2 + .../Native/WindowsApp.cs | 55 ++++++++++++++++++++++ 15 files changed, 126 insertions(+), 77 deletions(-) delete mode 100644 MediaBrowser.Controller/LiveTv/IHasRegistrationInfo.cs (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index f6817e0e7b..8868daacab 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -538,12 +538,6 @@ namespace MediaBrowser.Api.LiveTv [Authenticated] public class GetLiveTvRegistrationInfo : IReturn { - [ApiMember(Name = "ChannelId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public string ChannelId { get; set; } - - [ApiMember(Name = "ProgramId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] - public string ProgramId { get; set; } - [ApiMember(Name = "Feature", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string Feature { get; set; } } @@ -595,7 +589,7 @@ namespace MediaBrowser.Api.LiveTv public async Task Get(GetLiveTvRegistrationInfo request) { - var result = await _liveTvManager.GetRegistrationInfo(request.ChannelId, request.ProgramId, request.Feature).ConfigureAwait(false); + var result = await _liveTvManager.GetRegistrationInfo(request.Feature).ConfigureAwait(false); return ToOptimizedResult(result); } diff --git a/MediaBrowser.Controller/Library/NameExtensions.cs b/MediaBrowser.Controller/Library/NameExtensions.cs index 6973dce64f..72f036b0a5 100644 --- a/MediaBrowser.Controller/Library/NameExtensions.cs +++ b/MediaBrowser.Controller/Library/NameExtensions.cs @@ -54,7 +54,7 @@ namespace MediaBrowser.Controller.Library } } - class TextComparer : IComparer, IEqualityComparer + public class DistinctNameComparer : IComparer, IEqualityComparer { public int Compare(string x, string y) { @@ -63,7 +63,7 @@ namespace MediaBrowser.Controller.Library return 0; } - return string.Compare(x, y, CultureInfo.InvariantCulture, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace); + return string.Compare(x.RemoveDiacritics(), y.RemoveDiacritics(), StringComparison.OrdinalIgnoreCase); } public bool Equals(string x, string y) diff --git a/MediaBrowser.Controller/LiveTv/IHasRegistrationInfo.cs b/MediaBrowser.Controller/LiveTv/IHasRegistrationInfo.cs deleted file mode 100644 index 3626c18e54..0000000000 --- a/MediaBrowser.Controller/LiveTv/IHasRegistrationInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -using MediaBrowser.Model.Entities; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.LiveTv -{ - public interface IHasRegistrationInfo - { - /// - /// Gets the registration information. - /// - /// The feature. - /// Task<MBRegistrationRecord>. - Task GetRegistrationInfo(string feature); - } -} diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index ed64127c38..d30231eb96 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -364,11 +364,9 @@ namespace MediaBrowser.Controller.LiveTv /// /// Gets the registration information. /// - /// The channel identifier. - /// The program identifier. /// The feature. /// Task<MBRegistrationRecord>. - Task GetRegistrationInfo(string channelId, string programId, string feature); + Task GetRegistrationInfo(string feature); /// /// Adds the channel information. diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 5e74a39994..7cfd56c1ee 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -199,7 +199,6 @@ - diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 44a2ae9540..26bf3107d3 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -217,7 +217,7 @@ namespace MediaBrowser.Model.Configuration Migrations = new string[] { }; CodecsUsed = new string[] { }; SqliteCacheSize = 0; - ImageExtractionTimeoutMs = 10000; + ImageExtractionTimeoutMs = 14000; EnableLocalizedGuids = true; DisplaySpecialsWithinSeasons = true; diff --git a/MediaBrowser.Providers/Music/AudioMetadataService.cs b/MediaBrowser.Providers/Music/AudioMetadataService.cs index 5321281869..67ddd89812 100644 --- a/MediaBrowser.Providers/Music/AudioMetadataService.cs +++ b/MediaBrowser.Providers/Music/AudioMetadataService.cs @@ -6,6 +6,7 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; using System.Collections.Generic; +using System.Linq; using CommonIO; namespace MediaBrowser.Providers.Music @@ -21,7 +22,7 @@ namespace MediaBrowser.Providers.Music if (replaceData || targetItem.Artists.Count == 0) { - targetItem.Artists = sourceItem.Artists; + targetItem.Artists = sourceItem.Artists.ToList(); } if (replaceData || string.IsNullOrEmpty(targetItem.Album)) diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index be68162caf..9284f4fc74 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1168,6 +1168,26 @@ namespace MediaBrowser.Server.Implementations.Dto }; }) .ToList(); + + // Include artists that are not in the database yet, e.g., just added via metadata editor + var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList(); + dto.ArtistItems.AddRange(hasArtist.Artists + .Except(foundArtists, new DistinctNameComparer()) + .Select(i => + { + var artist = _libraryManager.GetArtist(i); + if (artist != null) + { + return new NameIdPair + { + Name = artist.Name, + Id = artist.Id.ToString("N") + }; + } + + return null; + + }).Where(i => i != null)); } var hasAlbumArtist = item as IHasAlbumArtist; diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 649024d160..8f5b42df06 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -33,7 +33,7 @@ using Microsoft.Win32; namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { - public class EmbyTV : ILiveTvService, ISupportsNewTimerIds, IHasRegistrationInfo, IDisposable + public class EmbyTV : ILiveTvService, ISupportsNewTimerIds, IDisposable { private readonly IApplicationHost _appHpst; private readonly ILogger _logger; @@ -46,7 +46,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private readonly LiveTvManager _liveTvManager; private readonly IFileSystem _fileSystem; - private readonly ISecurityManager _security; private readonly ILibraryMonitor _libraryMonitor; private readonly ILibraryManager _libraryManager; @@ -62,7 +61,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private readonly ConcurrentDictionary _activeRecordings = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ISecurityManager security, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder, IPowerManagement powerManagement) + public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder, IPowerManagement powerManagement) { Current = this; @@ -71,7 +70,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _httpClient = httpClient; _config = config; _fileSystem = fileSystem; - _security = security; _libraryManager = libraryManager; _libraryMonitor = libraryMonitor; _providerManager = providerManager; @@ -1114,7 +1112,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV if (config.EnableRecordingEncoding) { - var regInfo = await _security.GetRegistrationStatus("embytvrecordingconversion").ConfigureAwait(false); + var regInfo = await _liveTvManager.GetRegistrationInfo("embytvrecordingconversion").ConfigureAwait(false); if (regInfo.IsValid) { @@ -1171,8 +1169,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private async Task UpdateTimersForSeriesTimer(List epgData, SeriesTimerInfo seriesTimer, bool deleteInvalidTimers) { var newTimers = GetTimersForSeries(seriesTimer, epgData, true).ToList(); - - var registration = await GetRegistrationInfo("seriesrecordings").ConfigureAwait(false); + + var registration = await _liveTvManager.GetRegistrationInfo("seriesrecordings").ConfigureAwait(false); if (registration.IsValid) { @@ -1349,20 +1347,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV } } - public Task GetRegistrationInfo(string feature) - { - if (string.Equals(feature, "seriesrecordings", StringComparison.OrdinalIgnoreCase)) - { - return _security.GetRegistrationStatus("embytvseriesrecordings"); - } - - return Task.FromResult(new MBRegistrationRecord - { - IsValid = true, - IsRegistered = true - }); - } - public List GetRecordingFolders() { var list = new List(); diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 3d9a0f80ed..72d1dc120b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -31,6 +31,7 @@ using CommonIO; using IniParser; using IniParser.Model; using MediaBrowser.Common.Events; +using MediaBrowser.Common.Security; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Events; @@ -51,6 +52,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv private readonly ITaskManager _taskManager; private readonly IJsonSerializer _jsonSerializer; private readonly IProviderManager _providerManager; + private readonly ISecurityManager _security; private readonly IDtoService _dtoService; private readonly ILocalizationManager _localization; @@ -73,7 +75,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public event EventHandler> TimerCreated; public event EventHandler> SeriesTimerCreated; - public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager, IFileSystem fileSystem) + public LiveTvManager(IApplicationHost appHost, IServerConfigurationManager config, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, IProviderManager providerManager, IFileSystem fileSystem, ISecurityManager security) { _config = config; _logger = logger; @@ -85,6 +87,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv _jsonSerializer = jsonSerializer; _providerManager = providerManager; _fileSystem = fileSystem; + _security = security; _dtoService = dtoService; _userDataManager = userDataManager; @@ -2133,6 +2136,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv public async Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken) { + var registration = await GetRegistrationInfo("seriesrecordings").ConfigureAwait(false); + + if (!registration.IsValid) + { + _logger.Info("Creating series recordings requires an active Emby Premiere subscription."); + return; + } + var service = GetService(timer.ServiceName); var info = await _tvDtoService.GetSeriesTimerInfo(timer, true, this, cancellationToken).ConfigureAwait(false); @@ -2695,33 +2706,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } - public Task GetRegistrationInfo(string channelId, string programId, string feature) + public Task GetRegistrationInfo(string feature) { - ILiveTvService service; - - if (string.IsNullOrWhiteSpace(programId)) + if (string.Equals(feature, "seriesrecordings", StringComparison.OrdinalIgnoreCase)) { - var channel = GetInternalChannel(channelId); - service = GetService(channel); + feature = "embytvseriesrecordings"; } - else - { - var program = GetInternalProgram(programId); - service = GetService(program); - } - - var hasRegistration = service as IHasRegistrationInfo; - if (hasRegistration != null) - { - return hasRegistration.GetRegistrationInfo(feature); - } - - return Task.FromResult(new MBRegistrationRecord - { - IsValid = true, - IsRegistered = true - }); + return _security.GetRegistrationStatus(feature); } public List GetSatIniMappings() diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs index 2185f48047..48f6a2a48b 100644 --- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs @@ -283,6 +283,11 @@ namespace MediaBrowser.Server.Mono.Native { } + + public bool PortsRequireAuthorization(string applicationPath) + { + return false; + } } public class NullPowerManagement : IPowerManagement diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 86c5c06bc2..2417c5b11d 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -520,7 +520,7 @@ namespace MediaBrowser.Server.Startup.Common PlaylistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("PlaylistManager"), UserManager, ProviderManager); RegisterSingleInstance(PlaylistManager); - LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, ProviderManager, FileSystemManager); + LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, ProviderManager, FileSystemManager, SecurityManager); RegisterSingleInstance(LiveTvManager); UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager); @@ -773,7 +773,19 @@ namespace MediaBrowser.Server.Startup.Common /// protected override void FindParts() { - if (!ServerConfigurationManager.Configuration.IsPortAuthorized) + var isAuthorized = ServerConfigurationManager.Configuration.IsPortAuthorized; + if (isAuthorized) + { + try + { + isAuthorized = !NativeApp.PortsRequireAuthorization(ConfigurationManager.CommonApplicationPaths.ApplicationPath); + } + catch + { + + } + } + if (!isAuthorized) { RegisterServerWithAdministratorAccess(); ServerConfigurationManager.Configuration.IsPortAuthorized = true; diff --git a/MediaBrowser.Server.Startup.Common/INativeApp.cs b/MediaBrowser.Server.Startup.Common/INativeApp.cs index d2e278a3bb..9297a6d372 100644 --- a/MediaBrowser.Server.Startup.Common/INativeApp.cs +++ b/MediaBrowser.Server.Startup.Common/INativeApp.cs @@ -25,6 +25,8 @@ namespace MediaBrowser.Server.Startup.Common /// The temporary directory. void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory); + bool PortsRequireAuthorization(string applicationPath); + /// /// Gets the environment. /// diff --git a/MediaBrowser.ServerApplication/Native/RegisterServer.bat b/MediaBrowser.ServerApplication/Native/RegisterServer.bat index 27f863d581..85baa0d03a 100644 --- a/MediaBrowser.ServerApplication/Native/RegisterServer.bat +++ b/MediaBrowser.ServerApplication/Native/RegisterServer.bat @@ -20,7 +20,9 @@ netsh advfirewall firewall add rule name="Port %3" dir=in action=allow protocol= if [%4]==[] GOTO DONE +netsh advfirewall firewall delete rule name="mediabrowser.serverapplication.exe" netsh advfirewall firewall delete rule name="Emby Server" + netsh advfirewall firewall add rule name="Emby Server" dir=in action=allow protocol=TCP program=%4 enable=yes netsh advfirewall firewall add rule name="Emby Server" dir=in action=allow protocol=UDP program=%4 enable=yes diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 139471f11b..f7b19162d7 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -208,5 +208,60 @@ namespace MediaBrowser.ServerApplication.Native { LoopUtil.Run(appName); } + + public bool PortsRequireAuthorization(string applicationPath) + { + var appNameSrch = Path.GetFileName(applicationPath); + + var startInfo = new ProcessStartInfo + { + FileName = "netsh", + + Arguments = "advfirewall firewall show rule \"" + appNameSrch + "\"", + + CreateNoWindow = true, + UseShellExecute = false, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false, + RedirectStandardOutput = true + }; + + using (var process = Process.Start(startInfo)) + { + process.Start(); + + try + { + var data = process.StandardOutput.ReadToEnd() ?? string.Empty; + + //_logger.Debug("Found windows firewall rule: " + data); + if (data.IndexOf("Block", StringComparison.OrdinalIgnoreCase) != -1) + { + return true; + } + + //var parts = data.Split('\n'); + + //return parts.Length > 4; + return false; + } + catch (Exception ex) + { + _logger.ErrorException("Error querying windows firewall", ex); + + // Hate having to do this + try + { + process.Kill(); + } + catch (Exception ex1) + { + _logger.ErrorException("Error killing process", ex1); + } + + throw; + } + } + } } } \ No newline at end of file -- cgit v1.2.3 From c3f947f4da122343b87ec3c36364885d6f934d01 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 6 Sep 2016 13:59:10 -0400 Subject: add sports and kids recording categories --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 83 +++++++++++++++++++- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 1 + MediaBrowser.Model/LiveTv/RecordingQuery.cs | 2 + .../EntryPoints/UsageEntryPoint.cs | 6 +- .../LiveTv/LiveTvManager.cs | 91 +++++++++++++++++++++- .../Native/WindowsApp.cs | 2 +- 6 files changed, 177 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 8868daacab..3ad0ec1bae 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -157,6 +157,8 @@ namespace MediaBrowser.Api.LiveTv public bool? IsMovie { get; set; } public bool? IsSeries { get; set; } + public bool? IsKids { get; set; } + public bool? IsSports { get; set; } public GetRecordings() { @@ -164,6 +166,61 @@ namespace MediaBrowser.Api.LiveTv } } + [Route("/LiveTv/Recordings/Series", "GET", Summary = "Gets live tv recordings")] + [Authenticated] + public class GetRecordingSeries : IReturn>, IHasDtoOptions + { + [ApiMember(Name = "ChannelId", Description = "Optional filter by channel id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string ChannelId { get; set; } + + [ApiMember(Name = "UserId", Description = "Optional filter by user and attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string UserId { get; set; } + + [ApiMember(Name = "GroupId", Description = "Optional filter by recording group.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string GroupId { get; set; } + + [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? StartIndex { get; set; } + + [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? Limit { get; set; } + + [ApiMember(Name = "Status", Description = "Optional filter by recording status.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public RecordingStatus? Status { get; set; } + + [ApiMember(Name = "Status", Description = "Optional filter by recordings that are in progress, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] + public bool? IsInProgress { get; set; } + + [ApiMember(Name = "SeriesTimerId", Description = "Optional filter by recordings belonging to a series timer", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string SeriesTimerId { get; set; } + + [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] + public bool? EnableImages { get; set; } + + [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? ImageTypeLimit { get; set; } + + [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string EnableImageTypes { get; set; } + + /// + /// Fields to return within the items, in addition to basic information + /// + /// The fields. + [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] + public string Fields { get; set; } + + public bool EnableTotalRecordCount { get; set; } + + [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] + public bool? EnableUserData { get; set; } + + public GetRecordingSeries() + { + EnableTotalRecordCount = true; + } + } + [Route("/LiveTv/Recordings/Groups", "GET", Summary = "Gets live tv recording groups")] [Authenticated] public class GetRecordingGroups : IReturn> @@ -862,7 +919,31 @@ namespace MediaBrowser.Api.LiveTv IsInProgress = request.IsInProgress, EnableTotalRecordCount = request.EnableTotalRecordCount, IsMovie = request.IsMovie, - IsSeries = request.IsSeries + IsSeries = request.IsSeries, + IsKids = request.IsKids, + IsSports = request.IsSports + + }, options, CancellationToken.None).ConfigureAwait(false); + + return ToOptimizedResult(result); + } + + public async Task Get(GetRecordingSeries request) + { + var options = GetDtoOptions(request); + options.DeviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId; + + var result = await _liveTvManager.GetRecordingSeries(new RecordingQuery + { + ChannelId = request.ChannelId, + UserId = request.UserId, + GroupId = request.GroupId, + StartIndex = request.StartIndex, + Limit = request.Limit, + Status = request.Status, + SeriesTimerId = request.SeriesTimerId, + IsInProgress = request.IsInProgress, + EnableTotalRecordCount = request.EnableTotalRecordCount }, options, CancellationToken.None).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index d30231eb96..a8e42749b0 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -108,6 +108,7 @@ namespace MediaBrowser.Controller.LiveTv /// The cancellation token. /// QueryResult{RecordingInfoDto}. Task> GetRecordings(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken); + Task> GetRecordingSeries(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken); /// /// Gets the timers. diff --git a/MediaBrowser.Model/LiveTv/RecordingQuery.cs b/MediaBrowser.Model/LiveTv/RecordingQuery.cs index cedc0b8525..0ba5f17790 100644 --- a/MediaBrowser.Model/LiveTv/RecordingQuery.cs +++ b/MediaBrowser.Model/LiveTv/RecordingQuery.cs @@ -70,6 +70,8 @@ namespace MediaBrowser.Model.LiveTv public bool? EnableImages { get; set; } public bool? IsMovie { get; set; } public bool? IsSeries { get; set; } + public bool? IsKids { get; set; } + public bool? IsSports { get; set; } public int? ImageTypeLimit { get; set; } public ImageType[] EnableImageTypes { get; set; } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs index f82bb01bb3..d14bd43689 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs @@ -92,11 +92,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints DeviceId = session.DeviceId }; - // Report usage to remote server, except for web client, since we already have data on that - if (!string.Equals(info.AppName, "Dashboard", StringComparison.OrdinalIgnoreCase)) - { - ReportNewSession(info); - } + ReportNewSession(info); return info; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 72d1dc120b..e76f95ab4a 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1430,6 +1430,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv var includeItemTypes = new List(); var excludeItemTypes = new List(); + var genres = new List(); if (query.IsMovie.HasValue) { @@ -1453,6 +1454,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv excludeItemTypes.Add(typeof(Episode).Name); } } + if (query.IsSports.HasValue) + { + if (query.IsSports.Value) + { + genres.Add("Sports"); + } + } + if (query.IsKids.HasValue) + { + if (query.IsKids.Value) + { + genres.Add("Kids"); + genres.Add("Children"); + genres.Add("Family"); + } + } return _libraryManager.GetItemsResult(new InternalItemsQuery(user) { @@ -1461,13 +1478,73 @@ namespace MediaBrowser.Server.Implementations.LiveTv AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(), IsFolder = false, ExcludeLocationTypes = new[] { LocationType.Virtual }, - Limit = Math.Min(200, query.Limit ?? int.MaxValue), + Limit = query.Limit, + SortBy = new[] { ItemSortBy.DateCreated }, + SortOrder = SortOrder.Descending, + EnableTotalRecordCount = query.EnableTotalRecordCount, + IncludeItemTypes = includeItemTypes.ToArray(), + ExcludeItemTypes = excludeItemTypes.ToArray(), + Genres = genres.ToArray() + }); + } + + public async Task> GetRecordingSeries(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken) + { + var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); + if (user != null && !IsLiveTvEnabled(user)) + { + return new QueryResult(); + } + + if (_services.Count > 1) + { + return new QueryResult(); + } + + if (user == null || (query.IsInProgress ?? false)) + { + return new QueryResult(); + } + + var folders = EmbyTV.EmbyTV.Current.GetRecordingFolders() + .SelectMany(i => i.Locations) + .Distinct(StringComparer.OrdinalIgnoreCase) + .Select(i => _libraryManager.FindByPath(i, true)) + .Where(i => i != null) + .Where(i => i.IsVisibleStandalone(user)) + .ToList(); + + if (folders.Count == 0) + { + return new QueryResult(); + } + + var includeItemTypes = new List(); + var excludeItemTypes = new List(); + + includeItemTypes.Add(typeof(Series).Name); + + var internalResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user) + { + Recursive = true, + AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(), + Limit = query.Limit, SortBy = new[] { ItemSortBy.DateCreated }, SortOrder = SortOrder.Descending, EnableTotalRecordCount = query.EnableTotalRecordCount, IncludeItemTypes = includeItemTypes.ToArray(), ExcludeItemTypes = excludeItemTypes.ToArray() }); + + RemoveFields(options); + + var returnArray = (await _dtoService.GetBaseItemDtos(internalResult.Items, options, user).ConfigureAwait(false)).ToArray(); + + return new QueryResult + { + Items = returnArray, + TotalRecordCount = internalResult.TotalRecordCount + }; } public async Task> GetInternalRecordings(RecordingQuery query, CancellationToken cancellationToken) @@ -1537,6 +1614,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv recordings = recordings.Where(i => i.IsSeries == val); } + if (query.IsKids.HasValue) + { + var val = query.IsKids.Value; + recordings = recordings.Where(i => i.IsKids == val); + } + + if (query.IsSports.HasValue) + { + var val = query.IsSports.Value; + recordings = recordings.Where(i => i.IsSports == val); + } + if (!string.IsNullOrEmpty(query.SeriesTimerId)) { var guid = new Guid(query.SeriesTimerId); diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 2af6400e26..3cd6c95d2d 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -240,9 +240,9 @@ namespace MediaBrowser.ServerApplication.Native { var data = process.StandardOutput.ReadToEnd() ?? string.Empty; - //_logger.Debug("Found windows firewall rule: " + data); if (data.IndexOf("Block", StringComparison.OrdinalIgnoreCase) != -1) { + _logger.Info("Found windows firewall rule: " + data); return Confirm(); } -- cgit v1.2.3 From 4e0adb17e74a252f3168070721854a03ecc9d07b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 7 Sep 2016 01:48:14 -0400 Subject: update dialogs --- MediaBrowser.Controller/Library/ILibraryManager.cs | 3 +++ .../Library/LibraryManager.cs | 31 +++++++++++++++++++++- .../LiveTv/EmbyTV/EmbyTV.cs | 2 ++ .../Migrations/UpdateLevelMigration.cs | 6 ----- 4 files changed, 35 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 0862e3eaf9..04268bcea4 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -566,5 +566,8 @@ namespace MediaBrowser.Controller.Library QueryResult> GetArtists(InternalItemsQuery query); QueryResult> GetAlbumArtists(InternalItemsQuery query); QueryResult> GetAllArtists(InternalItemsQuery query); + + void RegisterIgnoredPath(string path); + void UnRegisterIgnoredPath(string path); } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 5d556e3a68..7758d690aa 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -621,9 +621,38 @@ namespace MediaBrowser.Server.Implementations.Library return ResolveItem(args, resolvers); } + private readonly List _ignoredPaths = new List(); + + public void RegisterIgnoredPath(string path) + { + lock (_ignoredPaths) + { + _ignoredPaths.Add(path); + } + } + public void UnRegisterIgnoredPath(string path) + { + lock (_ignoredPaths) + { + _ignoredPaths.Remove(path); + } + } + public bool IgnoreFile(FileSystemMetadata file, BaseItem parent) { - return EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent)); + if (EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent))) + { + return true; + } + + //lock (_ignoredPaths) + { + if (_ignoredPaths.Contains(file.FullName, StringComparer.OrdinalIgnoreCase)) + { + return true; + } + } + return false; } public IEnumerable NormalizeRootPathList(IEnumerable paths) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 8f5b42df06..8fa34109d2 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -993,6 +993,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath); recordPath = EnsureFileUnique(recordPath, timer.Id); + _libraryManager.RegisterIgnoredPath(recordPath); _libraryMonitor.ReportFileSystemChangeBeginning(recordPath); _fileSystem.CreateDirectory(Path.GetDirectoryName(recordPath)); activeRecordingInfo.Path = recordPath; @@ -1044,6 +1045,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV semaphore.Release(); } + _libraryManager.UnRegisterIgnoredPath(recordPath); _libraryMonitor.ReportFileSystemChangeComplete(recordPath, true); ActiveRecordingInfo removed; diff --git a/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs index de898e66cb..d5fe9707c8 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs @@ -42,12 +42,6 @@ namespace MediaBrowser.Server.Startup.Common.Migrations { var updateLevel = _config.Configuration.SystemUpdateLevel; - if (updateLevel == PackageVersionClass.Dev) - { - // It's already dev, there's nothing to check - return; - } - await CheckVersion(currentVersion, updateLevel, CancellationToken.None).ConfigureAwait(false); } catch -- cgit v1.2.3 From efebc78cf53c779611d9d7b3e7ed3c0dfcef2b1d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 8 Sep 2016 02:15:44 -0400 Subject: update prompt dialog --- .../LiveTv/Listings/SchedulesDirect.cs | 3 ++- .../LiveTv/LiveTvManager.cs | 14 +++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index e37109c148..206e90e40d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -785,9 +785,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings get { return "Schedules Direct"; } } + public static string TypeName = "SchedulesDirect"; public string Type { - get { return "SchedulesDirect"; } + get { return TypeName; } } private async Task HasLineup(ListingsProviderInfo info, CancellationToken cancellationToken) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index e76f95ab4a..a135a188eb 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -35,6 +35,7 @@ using MediaBrowser.Common.Security; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Events; +using MediaBrowser.Server.Implementations.LiveTv.Listings; namespace MediaBrowser.Server.Implementations.LiveTv { @@ -1436,7 +1437,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { if (query.IsMovie.Value) { - includeItemTypes.Add(typeof (Movie).Name); + includeItemTypes.Add(typeof(Movie).Name); } else { @@ -2802,6 +2803,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv feature = "embytvseriesrecordings"; } + var config = GetConfiguration(); + if (config.TunerHosts.Count(i => i.IsEnabled) > 0 && + config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0) + { + return Task.FromResult(new MBRegistrationRecord + { + IsRegistered = true, + IsValid = true + }); + } + return _security.GetRegistrationStatus(feature); } -- cgit v1.2.3 From 323d4104843dd50323c0d1378b4df5b65571bb8c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 8 Sep 2016 02:41:49 -0400 Subject: add option to save recordings as mkv --- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 2 ++ .../LiveTv/EmbyTV/EncodedRecorder.cs | 24 +++++++++++++++------- MediaBrowser.ServerApplication/MainStartup.cs | 2 +- .../Native/WindowsApp.cs | 9 ++++++-- 4 files changed, 27 insertions(+), 10 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 242a2d24e4..ee7dd8b985 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -13,6 +13,7 @@ namespace MediaBrowser.Model.LiveTv public string SeriesRecordingPath { get; set; } public bool EnableAutoOrganize { get; set; } public bool EnableRecordingEncoding { get; set; } + public string RecordingEncodingFormat { get; set; } public bool EnableRecordingSubfolders { get; set; } public bool EnableOriginalAudioWithEncodedRecordings { get; set; } @@ -31,6 +32,7 @@ namespace MediaBrowser.Model.LiveTv TunerHosts = new List(); ListingProviders = new List(); MediaLocationsCreated = new string[] { }; + RecordingEncodingFormat = "mp4"; } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 5e7e3a94f7..75ad3de59e 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -46,9 +46,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _httpClient = httpClient; } + private string OutputFormat + { + get + { + var format = _liveTvOptions.RecordingEncodingFormat; + + if (string.Equals(format, "mkv", StringComparison.OrdinalIgnoreCase)) + { + return "mkv"; + } + + return "mp4"; + } + } + public string GetOutputPath(MediaSourceInfo mediaSource, string targetFile) { - return Path.ChangeExtension(targetFile, ".mp4"); + return Path.ChangeExtension(targetFile, "." + OutputFormat); } public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) @@ -233,15 +248,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private string GetAudioArgs(MediaSourceInfo mediaSource) { - // do not copy aac because many players have difficulty with aac_latm - var copyAudio = new[] { "mp3" }; var mediaStreams = mediaSource.MediaStreams ?? new List(); var inputAudioCodec = mediaStreams.Where(i => i.Type == MediaStreamType.Audio).Select(i => i.Codec).FirstOrDefault() ?? string.Empty; - if (copyAudio.Contains(inputAudioCodec, StringComparer.OrdinalIgnoreCase)) - { - return "-codec:a:0 copy"; - } + // do not copy aac because many players have difficulty with aac_latm if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings && !string.Equals(inputAudioCodec, "aac", StringComparison.OrdinalIgnoreCase)) { return "-codec:a:0 copy"; diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 8fb0e8f46b..cdacdc81f8 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -331,7 +331,7 @@ namespace MediaBrowser.ServerApplication Application.Run(); } - private static SplashForm _splash; + internal static SplashForm _splash; private static Thread _splashThread; private static void ShowSplashScreen(Version appVersion, Progress progress, ILogger logger) { diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 3cd6c95d2d..200e2d3ae1 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -212,7 +212,12 @@ namespace MediaBrowser.ServerApplication.Native private bool Confirm() { - return MessageBox.Show("Emby has detected that Windows Firewall has been configured in a way that may prevent your other devices from accessing Emby Server. Click OK to remove this rule, or cancel to proceed anyway.", "Windows Firewall", MessageBoxButtons.OKCancel) == DialogResult.OK; + if (MainStartup._splash == null) + { + return false; + } + + return MessageBox.Show(MainStartup._splash, "Emby has detected that Windows Firewall has been configured in a way that may prevent your other devices from accessing Emby Server. Click OK to remove this rule, or cancel to proceed anyway.", "Windows Firewall", MessageBoxButtons.OKCancel) == DialogResult.OK; } public bool PortsRequireAuthorization(string applicationPath) @@ -242,7 +247,7 @@ namespace MediaBrowser.ServerApplication.Native if (data.IndexOf("Block", StringComparison.OrdinalIgnoreCase) != -1) { - _logger.Info("Found windows firewall rule: " + data); + _logger.Info("Found potential windows firewall rule blocking Emby Server: " + data); return Confirm(); } -- cgit v1.2.3 From 232b5758f08e8e748427dcef7d7bdc7c0d7b94ae Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 8 Sep 2016 16:32:30 -0400 Subject: update dialogs --- MediaBrowser.Controller/LiveTv/ProgramInfo.cs | 7 +++++++ MediaBrowser.Model/Configuration/ServerConfiguration.cs | 1 + MediaBrowser.Model/LiveTv/ProgramAudio.cs | 3 ++- .../LiveTv/Listings/SchedulesDirect.cs | 7 ++++++- .../LiveTv/LiveTvManager.cs | 17 ++++++++++------- 5 files changed, 26 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Controller/LiveTv/ProgramInfo.cs b/MediaBrowser.Controller/LiveTv/ProgramInfo.cs index a6a3e61081..ea5e6dbc6a 100644 --- a/MediaBrowser.Controller/LiveTv/ProgramInfo.cs +++ b/MediaBrowser.Controller/LiveTv/ProgramInfo.cs @@ -1,6 +1,7 @@ using MediaBrowser.Model.LiveTv; using System; using System.Collections.Generic; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.LiveTv { @@ -66,6 +67,8 @@ namespace MediaBrowser.Controller.LiveTv /// true if this instance is hd; otherwise, false. public bool? IsHD { get; set; } + public bool? Is3D { get; set; } + /// /// Gets or sets the audio. /// @@ -84,6 +87,8 @@ namespace MediaBrowser.Controller.LiveTv /// true if this instance is repeat; otherwise, false. public bool IsRepeat { get; set; } + public bool IsSubjectToBlackout { get; set; } + /// /// Gets or sets the episode title. /// @@ -144,6 +149,8 @@ namespace MediaBrowser.Controller.LiveTv /// true if this instance is kids; otherwise, false. public bool IsKids { get; set; } + public bool IsEducational { get; set; } + /// /// Gets or sets a value indicating whether this instance is premiere. /// diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 26bf3107d3..a444afb07f 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -234,6 +234,7 @@ namespace MediaBrowser.Model.Configuration EnableAnonymousUsageReporting = true; EnableAutomaticRestart = true; + EnableFolderView = true; EnableUPnP = true; SharingExpirationDays = 30; diff --git a/MediaBrowser.Model/LiveTv/ProgramAudio.cs b/MediaBrowser.Model/LiveTv/ProgramAudio.cs index 902079b9ab..9a272492ca 100644 --- a/MediaBrowser.Model/LiveTv/ProgramAudio.cs +++ b/MediaBrowser.Model/LiveTv/ProgramAudio.cs @@ -6,6 +6,7 @@ Stereo, Dolby, DolbyDigital, - Thx + Thx, + Atmos } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 206e90e40d..7cac875902 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -348,7 +348,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings if (programInfo.audioProperties != null) { - if (programInfo.audioProperties.Exists(item => string.Equals(item, "dd 5.1", StringComparison.OrdinalIgnoreCase))) + if (programInfo.audioProperties.Exists(item => string.Equals(item, "atmos", StringComparison.OrdinalIgnoreCase))) + { + audioType = ProgramAudio.Atmos; + } + else if (programInfo.audioProperties.Exists(item => string.Equals(item, "dd 5.1", StringComparison.OrdinalIgnoreCase))) { audioType = ProgramAudio.DolbyDigital; } @@ -405,6 +409,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings if (programInfo.videoProperties != null) { info.IsHD = programInfo.videoProperties.Contains("hdtv", StringComparer.OrdinalIgnoreCase); + info.Is3D = programInfo.videoProperties.Contains("3d", StringComparer.OrdinalIgnoreCase); } if (details.contentRating != null && details.contentRating.Count > 0) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index a135a188eb..b3ced55a51 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2803,15 +2803,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv feature = "embytvseriesrecordings"; } - var config = GetConfiguration(); - if (config.TunerHosts.Count(i => i.IsEnabled) > 0 && - config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0) + if (string.Equals(feature, "dvr", StringComparison.OrdinalIgnoreCase)) { - return Task.FromResult(new MBRegistrationRecord + var config = GetConfiguration(); + if (config.TunerHosts.Count(i => i.IsEnabled) > 0 && + config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0) { - IsRegistered = true, - IsValid = true - }); + return Task.FromResult(new MBRegistrationRecord + { + IsRegistered = true, + IsValid = true + }); + } } return _security.GetRegistrationStatus(feature); -- cgit v1.2.3 From 906546ca5e5ae1a4d6ef38b3be8744a3111ac6c6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 9 Sep 2016 02:59:23 -0400 Subject: update dialogs --- .../Updates/GithubUpdater.cs | 16 +++------ .../LiveTv/Listings/SchedulesDirect.cs | 18 +++++++--- .../ApplicationHost.cs | 4 +-- .../Migrations/UpdateLevelMigration.cs | 2 +- .../Native/WindowsApp.cs | 2 +- MediaBrowser.WebDashboard/Api/DashboardService.cs | 38 ---------------------- 6 files changed, 21 insertions(+), 59 deletions(-) (limited to 'MediaBrowser.Server.Implementations/LiveTv') diff --git a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs index 6281ab3edb..84c08439ee 100644 --- a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs +++ b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs @@ -14,16 +14,14 @@ namespace MediaBrowser.Common.Implementations.Updates { private readonly IHttpClient _httpClient; private readonly IJsonSerializer _jsonSerializer; - private TimeSpan _cacheLength; - public GithubUpdater(IHttpClient httpClient, IJsonSerializer jsonSerializer, TimeSpan cacheLength) + public GithubUpdater(IHttpClient httpClient, IJsonSerializer jsonSerializer) { _httpClient = httpClient; _jsonSerializer = jsonSerializer; - _cacheLength = cacheLength; } - public async Task CheckForUpdateResult(string organzation, string repository, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename, CancellationToken cancellationToken) + public async Task CheckForUpdateResult(string organzation, string repository, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename, TimeSpan cacheLength, CancellationToken cancellationToken) { var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository); @@ -35,10 +33,10 @@ namespace MediaBrowser.Common.Implementations.Updates UserAgent = "Emby/3.0" }; - if (_cacheLength.Ticks > 0) + if (cacheLength.Ticks > 0) { options.CacheMode = CacheMode.Unconditional; - options.CacheLength = _cacheLength; + options.CacheLength = cacheLength; } using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) @@ -110,12 +108,6 @@ namespace MediaBrowser.Common.Implementations.Updates UserAgent = "Emby/3.0" }; - if (_cacheLength.Ticks > 0) - { - options.CacheMode = CacheMode.Unconditional; - options.CacheLength = _cacheLength; - } - using (var stream = await _httpClient.Get(options).ConfigureAwait(false)) { var obj = _jsonSerializer.DeserializeFromStream(stream); diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 7cac875902..1a5ebedc2a 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -194,14 +194,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings return station; } - if (string.IsNullOrWhiteSpace(channelName)) + if (!string.IsNullOrWhiteSpace(channelName)) { - return null; - } + channelName = NormalizeName(channelName); - channelName = NormalizeName(channelName); + var result = channelPair.Values.FirstOrDefault(i => string.Equals(NormalizeName(i.callsign ?? string.Empty), channelName, StringComparison.OrdinalIgnoreCase)); - return channelPair.Values.FirstOrDefault(i => string.Equals(NormalizeName(i.callsign ?? string.Empty), channelName, StringComparison.OrdinalIgnoreCase)); + if (result != null) + { + return result; + } + } + + if (!string.IsNullOrWhiteSpace(channelNumber)) + { + return channelPair.Values.FirstOrDefault(i => string.Equals(NormalizeName(i.stationID ?? string.Empty), channelNumber, StringComparison.OrdinalIgnoreCase)); + } } return null; diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 07659fdfc6..703d8242f6 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -1345,8 +1345,8 @@ namespace MediaBrowser.Server.Startup.Common cacheLength = TimeSpan.FromMinutes(5); } - var result = await new GithubUpdater(HttpClient, JsonSerializer, cacheLength).CheckForUpdateResult("MediaBrowser", "Emby", ApplicationVersion, updateLevel, _releaseAssetFilename, - "MBServer", "Mbserver.zip", cancellationToken).ConfigureAwait(false); + var result = await new GithubUpdater(HttpClient, JsonSerializer).CheckForUpdateResult("MediaBrowser", "Emby", ApplicationVersion, updateLevel, _releaseAssetFilename, + "MBServer", "Mbserver.zip", cacheLength, cancellationToken).ConfigureAwait(false); HasUpdateAvailable = result.IsUpdateAvailable; diff --git a/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs b/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs index d5fe9707c8..4afd5bd344 100644 --- a/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs +++ b/MediaBrowser.Server.Startup.Common/Migrations/UpdateLevelMigration.cs @@ -52,7 +52,7 @@ namespace MediaBrowser.Server.Startup.Common.Migrations private async Task CheckVersion(Version currentVersion, PackageVersionClass currentUpdateLevel, CancellationToken cancellationToken) { - var releases = await new GithubUpdater(_httpClient, _jsonSerializer, TimeSpan.FromMinutes(3)) + var releases = await new GithubUpdater(_httpClient, _jsonSerializer) .GetLatestReleases("MediaBrowser", "Emby", _releaseAssetFilename, cancellationToken).ConfigureAwait(false); var newUpdateLevel = GetNewUpdateLevel(currentVersion, currentUpdateLevel, releases); diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 200e2d3ae1..b08b82de53 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -217,7 +217,7 @@ namespace MediaBrowser.ServerApplication.Native return false; } - return MessageBox.Show(MainStartup._splash, "Emby has detected that Windows Firewall has been configured in a way that may prevent your other devices from accessing Emby Server. Click OK to remove this rule, or cancel to proceed anyway.", "Windows Firewall", MessageBoxButtons.OKCancel) == DialogResult.OK; + return MessageBox.Show(MainStartup._splash, "Emby has detected that a rule has been added to Windows Firewall that may prevent your other devices from accessing Emby Server. Click OK to remove this rule, or cancel to proceed anyway.", "Windows Firewall", MessageBoxButtons.OKCancel) == DialogResult.OK; } public bool PortsRequireAuthorization(string applicationPath) diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index aec4632ae8..2f8b348791 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -58,11 +58,6 @@ namespace MediaBrowser.WebDashboard.Api { } - [Route("/web/staticfiles", "GET")] - public class GetCacheFiles - { - } - /// /// Class GetDashboardResource /// @@ -145,37 +140,6 @@ namespace MediaBrowser.WebDashboard.Api return ResultFactory.GetStaticResult(Request, page.Plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator().ModifyHtml("dummy.html", page.GetHtmlStream(), null, _appHost.ApplicationVersion.ToString(), null, false)); } - public object Get(GetCacheFiles request) - { - var allFiles = GetCacheFileList(); - - return ResultFactory.GetOptimizedResult(Request, _jsonSerializer.SerializeToString(allFiles)); - } - - private List GetCacheFileList() - { - var creator = GetPackageCreator(); - var directory = creator.DashboardUIPath; - - var skipExtensions = GetDeployIgnoreExtensions(); - var skipNames = GetDeployIgnoreFilenames(); - - return - Directory.GetFiles(directory, "*", SearchOption.AllDirectories) - .Where(i => !skipExtensions.Contains(Path.GetExtension(i) ?? string.Empty, StringComparer.OrdinalIgnoreCase)) - .Where(i => !skipNames.Any(s => - { - if (s.Item2) - { - return string.Equals(s.Item1, Path.GetFileName(i), StringComparison.OrdinalIgnoreCase); - } - - return (Path.GetFileName(i) ?? string.Empty).IndexOf(s.Item1, StringComparison.OrdinalIgnoreCase) != -1; - })) - .Select(i => i.Replace(directory, string.Empty, StringComparison.OrdinalIgnoreCase).Replace("\\", "/").TrimStart('/') + "?v=" + _appHost.ApplicationVersion.ToString()) - .ToList(); - } - /// /// Gets the specified request. /// @@ -369,8 +333,6 @@ namespace MediaBrowser.WebDashboard.Api var appVersion = _appHost.ApplicationVersion.ToString(); - File.WriteAllText(Path.Combine(path, "staticfiles"), _jsonSerializer.SerializeToString(GetCacheFileList())); - var mode = request.Mode; // Try to trim the output size a bit -- cgit v1.2.3