|
@@ -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,16 +111,10 @@ 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))
|
|
{
|
|
{
|
|
if (!_lockkey.HasValue)
|
|
if (!_lockkey.HasValue)
|
|
@@ -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);
|
|
|
|
- await tcpClient.SendAsync(channelMsg, channelMsg.Length, ipEndPoint, cancellationToken).ConfigureAwait(false);
|
|
|
|
- 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);
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (program != String.Empty)
|
|
|
|
|
|
+ var commandList = commands.GetCommands();
|
|
|
|
+ foreach(Tuple<string,string> command in commandList)
|
|
{
|
|
{
|
|
- var programMsg = CreateSetMessage(i, "program", program, _lockkey.Value);
|
|
|
|
- await tcpClient.SendAsync(programMsg, programMsg.Length, ipEndPoint, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
+ var channelMsg = CreateSetMessage(i, command.Item1, command.Item2, _lockkey.Value);
|
|
|
|
+ await tcpClient.SendAsync(channelMsg, channelMsg.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,8 +152,9 @@ 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);
|
|
var targetMsg = CreateSetMessage(i, "target", targetValue, _lockkey.Value);
|
|
var targetMsg = CreateSetMessage(i, "target", targetValue, _lockkey.Value);
|
|
|
|
|
|
@@ -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));
|