update legacy hdhomerun support
This commit is contained in:
parent
00fb471162
commit
9e74d834a7
|
@ -39,7 +39,15 @@ namespace Emby.Server.Core.Localization
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return text.Normalize(form);
|
try
|
||||||
|
{
|
||||||
|
return text.Normalize(form);
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
// if it still fails, return the original text
|
||||||
|
return text;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string StripInvalidUnicodeCharacters(string str)
|
private static string StripInvalidUnicodeCharacters(string str)
|
||||||
|
|
|
@ -579,7 +579,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ErrorHandler(new FileNotFoundException(), httpReq);
|
ErrorHandler(new FileNotFoundException(), httpReq, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException ex)
|
catch (OperationCanceledException ex)
|
||||||
|
@ -633,7 +633,6 @@ namespace Emby.Server.Implementations.HttpServer
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void Write(IResponse response, string text)
|
private void Write(IResponse response, string text)
|
||||||
{
|
{
|
||||||
var bOutput = Encoding.UTF8.GetBytes(text);
|
var bOutput = Encoding.UTF8.GetBytes(text);
|
||||||
|
|
|
@ -69,9 +69,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
|
|
||||||
private async Task<List<Channels>> GetLineup(TunerHostInfo info, CancellationToken cancellationToken)
|
private async Task<List<Channels>> GetLineup(TunerHostInfo info, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var options = new HttpRequestOptions
|
var options = new HttpRequestOptions
|
||||||
{
|
{
|
||||||
Url = string.Format("{0}/lineup.json", GetApiUrl(info, false)),
|
Url = model.LineupURL,
|
||||||
CancellationToken = cancellationToken,
|
CancellationToken = cancellationToken,
|
||||||
BufferContent = false
|
BufferContent = false
|
||||||
};
|
};
|
||||||
|
@ -451,7 +453,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
|
|
||||||
string nal = null;
|
string nal = null;
|
||||||
|
|
||||||
var url = info.Url;
|
var url = GetApiUrl(info, false);
|
||||||
var id = channelId;
|
var id = channelId;
|
||||||
id += "_" + url.GetMD5().ToString("N");
|
id += "_" + url.GetMD5().ToString("N");
|
||||||
|
|
||||||
|
@ -586,18 +588,17 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
|
|
||||||
if (hdhomerunChannel != null && hdhomerunChannel.IsLegacyTuner)
|
if (hdhomerunChannel != null && hdhomerunChannel.IsLegacyTuner)
|
||||||
{
|
{
|
||||||
var modelInfo = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
|
|
||||||
var mediaSource = GetLegacyMediaSource(info, hdhrId, channelInfo);
|
var mediaSource = GetLegacyMediaSource(info, hdhrId, channelInfo);
|
||||||
|
var modelInfo = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var liveStream = new HdHomerunUdpStream(mediaSource, streamId, hdhomerunChannel.Url, modelInfo.TunerCount, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager);
|
return new HdHomerunUdpStream(mediaSource, streamId, new LegacyHdHomerunChannelCommands(hdhomerunChannel.Url), modelInfo.TunerCount, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager);
|
||||||
return liveStream;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var mediaSource = GetMediaSource(info, hdhrId, channelInfo, profile);
|
var mediaSource = GetMediaSource(info, hdhrId, channelInfo, profile);
|
||||||
|
|
||||||
var liveStream = new HdHomerunHttpStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost);
|
return new HdHomerunHttpStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost);
|
||||||
return liveStream;
|
//return new HdHomerunUdpStream(mediaSource, streamId, new HdHomerunChannelCommands(hdhomerunChannel.Number), modelInfo.TunerCount, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,60 @@ using MediaBrowser.Model.Net;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
{
|
{
|
||||||
|
public interface IHdHomerunChannelCommands
|
||||||
|
{
|
||||||
|
IEnumerable<Tuple<string, string>> GetCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LegacyHdHomerunChannelCommands : IHdHomerunChannelCommands
|
||||||
|
{
|
||||||
|
private string _channel;
|
||||||
|
private string _program;
|
||||||
|
public LegacyHdHomerunChannelCommands(string url)
|
||||||
|
{
|
||||||
|
// parse url for channel and program
|
||||||
|
var regExp = new Regex(@"\/ch(\d+)-?(\d*)");
|
||||||
|
var match = regExp.Match(url);
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
_channel = match.Groups[1].Value;
|
||||||
|
_program = match.Groups[2].Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Tuple<string, string>> GetCommands()
|
||||||
|
{
|
||||||
|
var commands = new List<Tuple<string, string>>();
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(_channel))
|
||||||
|
commands.Add(Tuple.Create("channel", _channel));
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(_program))
|
||||||
|
commands.Add(Tuple.Create("program", _program));
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HdHomerunChannelCommands : IHdHomerunChannelCommands
|
||||||
|
{
|
||||||
|
private string _channel;
|
||||||
|
|
||||||
|
public HdHomerunChannelCommands(string channel)
|
||||||
|
{
|
||||||
|
_channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Tuple<string, string>> GetCommands()
|
||||||
|
{
|
||||||
|
var commands = new List<Tuple<string, string>>();
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(_channel))
|
||||||
|
commands.Add(Tuple.Create("vchannel", _channel));
|
||||||
|
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class HdHomerunManager : IDisposable
|
public class HdHomerunManager : IDisposable
|
||||||
{
|
{
|
||||||
public static int HdHomeRunPort = 65001;
|
public static int HdHomeRunPort = 65001;
|
||||||
|
@ -57,15 +111,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
return string.Equals(returnVal, "none", StringComparison.OrdinalIgnoreCase);
|
return string.Equals(returnVal, "none", StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartStreaming(IpAddressInfo remoteIp, IpAddressInfo localIp, int localPort, string url, int numTuners, CancellationToken cancellationToken)
|
public async Task StartStreaming(IpAddressInfo remoteIp, IpAddressInfo localIp, int localPort, IHdHomerunChannelCommands commands, int numTuners, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_remoteIp = remoteIp;
|
_remoteIp = remoteIp;
|
||||||
// parse url for channel and program
|
|
||||||
string frequency, program;
|
|
||||||
if (!ParseUrl(url, out frequency, out program))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var tcpClient = _socketFactory.CreateTcpSocket(_remoteIp, HdHomeRunPort))
|
using (var tcpClient = _socketFactory.CreateTcpSocket(_remoteIp, HdHomeRunPort))
|
||||||
{
|
{
|
||||||
|
@ -92,20 +140,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out returnVal))
|
if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out returnVal))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var channelMsg = CreateSetMessage(i, "channel", frequency, _lockkey.Value);
|
var commandList = commands.GetCommands();
|
||||||
await tcpClient.SendAsync(channelMsg, channelMsg.Length, ipEndPoint, cancellationToken).ConfigureAwait(false);
|
foreach(Tuple<string,string> command in commandList)
|
||||||
await tcpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false);
|
|
||||||
// parse response to make sure it worked
|
|
||||||
if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out returnVal))
|
|
||||||
{
|
{
|
||||||
await ReleaseLockkey(tcpClient).ConfigureAwait(false);
|
var channelMsg = CreateSetMessage(i, command.Item1, command.Item2, _lockkey.Value);
|
||||||
continue;
|
await tcpClient.SendAsync(channelMsg, channelMsg.Length, ipEndPoint, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
|
||||||
|
|
||||||
if (program != String.Empty)
|
|
||||||
{
|
|
||||||
var programMsg = CreateSetMessage(i, "program", program, _lockkey.Value);
|
|
||||||
await tcpClient.SendAsync(programMsg, programMsg.Length, ipEndPoint, cancellationToken).ConfigureAwait(false);
|
|
||||||
await tcpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false);
|
await tcpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false);
|
||||||
// parse response to make sure it worked
|
// parse response to make sure it worked
|
||||||
if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out returnVal))
|
if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out returnVal))
|
||||||
|
@ -113,6 +152,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
await ReleaseLockkey(tcpClient).ConfigureAwait(false);
|
await ReleaseLockkey(tcpClient).ConfigureAwait(false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var targetValue = String.Format("rtp://{0}:{1}", localIp, localPort);
|
var targetValue = String.Format("rtp://{0}:{1}", localIp, localPort);
|
||||||
|
@ -154,22 +194,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
await tcpClient.ReceiveAsync(CancellationToken.None).ConfigureAwait(false);
|
await tcpClient.ReceiveAsync(CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ParseUrl(string url, out string frequency, out string program)
|
|
||||||
{
|
|
||||||
frequency = String.Empty;
|
|
||||||
program = String.Empty;
|
|
||||||
var regExp = new Regex(@"\/ch(\d+)-?(\d*)");
|
|
||||||
var match = regExp.Match(url);
|
|
||||||
if (match.Success)
|
|
||||||
{
|
|
||||||
frequency = match.Groups[1].Value;
|
|
||||||
program = match.Groups[2].Value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] CreateGetMessage(int tuner, string name)
|
private static byte[] CreateGetMessage(int tuner, string name)
|
||||||
{
|
{
|
||||||
var byteName = Encoding.UTF8.GetBytes(String.Format("/tuner{0}/{1}\0", tuner, name));
|
var byteName = Encoding.UTF8.GetBytes(String.Format("/tuner{0}/{1}\0", tuner, name));
|
||||||
|
|
|
@ -29,11 +29,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource();
|
private readonly CancellationTokenSource _liveStreamCancellationTokenSource = new CancellationTokenSource();
|
||||||
private readonly TaskCompletionSource<bool> _liveStreamTaskCompletionSource = new TaskCompletionSource<bool>();
|
private readonly TaskCompletionSource<bool> _liveStreamTaskCompletionSource = new TaskCompletionSource<bool>();
|
||||||
private readonly MulticastStream _multicastStream;
|
private readonly MulticastStream _multicastStream;
|
||||||
private readonly string _channelUrl;
|
private readonly IHdHomerunChannelCommands _channelCommands;
|
||||||
private readonly int _numTuners;
|
private readonly int _numTuners;
|
||||||
private readonly INetworkManager _networkManager;
|
private readonly INetworkManager _networkManager;
|
||||||
|
|
||||||
public HdHomerunUdpStream(MediaSourceInfo mediaSource, string originalStreamId, string channelUrl, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager)
|
public HdHomerunUdpStream(MediaSourceInfo mediaSource, string originalStreamId, IHdHomerunChannelCommands channelCommands, int numTuners, IFileSystem fileSystem, IHttpClient httpClient, ILogger logger, IServerApplicationPaths appPaths, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager)
|
||||||
: base(mediaSource)
|
: base(mediaSource)
|
||||||
{
|
{
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
|
@ -45,7 +45,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
_networkManager = networkManager;
|
_networkManager = networkManager;
|
||||||
OriginalStreamId = originalStreamId;
|
OriginalStreamId = originalStreamId;
|
||||||
_multicastStream = new MulticastStream(_logger);
|
_multicastStream = new MulticastStream(_logger);
|
||||||
_channelUrl = channelUrl;
|
_channelCommands = channelCommands;
|
||||||
_numTuners = numTuners;
|
_numTuners = numTuners;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,10 +118,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// send url to start streaming
|
// send url to start streaming
|
||||||
await hdHomerunManager.StartStreaming(remoteAddress, localAddress, localPort, _channelUrl, _numTuners, cancellationToken).ConfigureAwait(false);
|
await hdHomerunManager.StartStreaming(remoteAddress, localAddress, localPort, _channelCommands, _numTuners, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var response = await udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false);
|
var response = await udpClient.ReceiveAsync(cancellationToken).ConfigureAwait(false);
|
||||||
_logger.Info("Opened HDHR UDP stream from {0}", _channelUrl);
|
_logger.Info("Opened HDHR UDP stream from {0}", remoteAddress);
|
||||||
|
|
||||||
if (!cancellationToken.IsCancellationRequested)
|
if (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,7 +16,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
private const int BufferSize = 81920;
|
private const int BufferSize = 81920;
|
||||||
private CancellationToken _cancellationToken;
|
private CancellationToken _cancellationToken;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly ConcurrentQueue<byte[]> _sharedBuffer = new ConcurrentQueue<byte[]>();
|
|
||||||
|
|
||||||
public MulticastStream(ILogger logger)
|
public MulticastStream(ILogger logger)
|
||||||
{
|
{
|
||||||
|
@ -38,14 +37,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
byte[] copy = new byte[bytesRead];
|
byte[] copy = new byte[bytesRead];
|
||||||
Buffer.BlockCopy(buffer, 0, copy, 0, bytesRead);
|
Buffer.BlockCopy(buffer, 0, copy, 0, bytesRead);
|
||||||
|
|
||||||
_sharedBuffer.Enqueue(copy);
|
|
||||||
|
|
||||||
while (_sharedBuffer.Count > 10000)
|
|
||||||
{
|
|
||||||
byte[] bytes;
|
|
||||||
_sharedBuffer.TryDequeue(out bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
var allStreams = _outputStreams.ToList();
|
var allStreams = _outputStreams.ToList();
|
||||||
foreach (var stream in allStreams)
|
foreach (var stream in allStreams)
|
||||||
{
|
{
|
||||||
|
@ -74,16 +65,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
||||||
OnFinished = OnFinished
|
OnFinished = OnFinished
|
||||||
};
|
};
|
||||||
|
|
||||||
var list = new List<byte>();
|
|
||||||
foreach (var bytes in _sharedBuffer)
|
|
||||||
{
|
|
||||||
list.AddRange(bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.Info("QueueStream started with {0} initial bytes", list.Count);
|
|
||||||
|
|
||||||
result.Queue(list.ToArray());
|
|
||||||
|
|
||||||
_outputStreams.TryAdd(result.Id, result);
|
_outputStreams.TryAdd(result.Id, result);
|
||||||
|
|
||||||
result.Start(_cancellationToken);
|
result.Start(_cancellationToken);
|
||||||
|
|
|
@ -170,11 +170,6 @@ namespace MediaBrowser.Providers.TV
|
||||||
/// <exception cref="System.ArgumentNullException">seriesId</exception>
|
/// <exception cref="System.ArgumentNullException">seriesId</exception>
|
||||||
internal async Task DownloadSeriesZip(string seriesId, string idType, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, CancellationToken cancellationToken)
|
internal async Task DownloadSeriesZip(string seriesId, string idType, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(seriesId))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("seriesId");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await DownloadSeriesZip(seriesId, idType, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
await DownloadSeriesZip(seriesId, idType, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>MediaBrowser.Common</id>
|
<id>MediaBrowser.Common</id>
|
||||||
<version>3.0.695</version>
|
<version>3.0.696</version>
|
||||||
<title>Emby.Common</title>
|
<title>Emby.Common</title>
|
||||||
<authors>Emby Team</authors>
|
<authors>Emby Team</authors>
|
||||||
<owners>ebr,Luke,scottisafool</owners>
|
<owners>ebr,Luke,scottisafool</owners>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>MediaBrowser.Server.Core</id>
|
<id>MediaBrowser.Server.Core</id>
|
||||||
<version>3.0.695</version>
|
<version>3.0.696</version>
|
||||||
<title>Emby.Server.Core</title>
|
<title>Emby.Server.Core</title>
|
||||||
<authors>Emby Team</authors>
|
<authors>Emby Team</authors>
|
||||||
<owners>ebr,Luke,scottisafool</owners>
|
<owners>ebr,Luke,scottisafool</owners>
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
<description>Contains core components required to build plugins for Emby Server.</description>
|
<description>Contains core components required to build plugins for Emby Server.</description>
|
||||||
<copyright>Copyright © Emby 2013</copyright>
|
<copyright>Copyright © Emby 2013</copyright>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MediaBrowser.Common" version="3.0.695" />
|
<dependency id="MediaBrowser.Common" version="3.0.696" />
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("3.2.5.6")]
|
[assembly: AssemblyVersion("3.2.5.7")]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user