aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Common.Implementations/Net/UdpSocket.cs143
-rw-r--r--Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs46
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs29
-rw-r--r--SharedVersion.cs2
4 files changed, 159 insertions, 61 deletions
diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs
index 94d073bd2..a97b2e668 100644
--- a/Emby.Common.Implementations/Net/UdpSocket.cs
+++ b/Emby.Common.Implementations/Net/UdpSocket.cs
@@ -49,7 +49,7 @@ namespace Emby.Common.Implementations.Net
private void InitReceiveSocketAsyncEventArgs()
{
- var receiveBuffer = new byte[8192];
+ var receiveBuffer = new byte[81920];
_receiveSocketAsyncEventArgs.SetBuffer(receiveBuffer, 0, receiveBuffer.Length);
_receiveSocketAsyncEventArgs.Completed += _receiveSocketAsyncEventArgs_Completed;
@@ -119,20 +119,29 @@ namespace Emby.Common.Implementations.Net
public Task<SocketReceiveResult> ReceiveAsync(CancellationToken cancellationToken)
{
ThrowIfDisposed();
-
var tcs = new TaskCompletionSource<SocketReceiveResult>();
-
EndPoint receivedFromEndPoint = new IPEndPoint(IPAddress.Any, 0);
+
+ var state = new AsyncReceiveState(_Socket, receivedFromEndPoint);
+ state.TaskCompletionSource = tcs;
+
cancellationToken.Register(() => tcs.TrySetCanceled());
_receiveSocketAsyncEventArgs.RemoteEndPoint = receivedFromEndPoint;
_currentReceiveTaskCompletionSource = tcs;
- var willRaiseEvent = _Socket.ReceiveFromAsync(_receiveSocketAsyncEventArgs);
+ try
+ {
+ var willRaiseEvent = _Socket.ReceiveFromAsync(_receiveSocketAsyncEventArgs);
- if (!willRaiseEvent)
+ if (!willRaiseEvent)
+ {
+ _receiveSocketAsyncEventArgs_Completed(this, _receiveSocketAsyncEventArgs);
+ }
+ }
+ catch (Exception ex)
{
- _receiveSocketAsyncEventArgs_Completed(this, _receiveSocketAsyncEventArgs);
+ tcs.TrySetException(ex);
}
return tcs.Task;
@@ -145,31 +154,82 @@ namespace Emby.Common.Implementations.Net
if (buffer == null) throw new ArgumentNullException("messageData");
if (endPoint == null) throw new ArgumentNullException("endPoint");
- cancellationToken.ThrowIfCancellationRequested();
+ var ipEndPoint = NetworkManager.ToIPEndPoint(endPoint);
- var tcs = new TaskCompletionSource<int>();
+#if NETSTANDARD1_6
- cancellationToken.Register(() => tcs.TrySetCanceled());
+ if (size != buffer.Length)
+ {
+ byte[] copy = new byte[size];
+ Buffer.BlockCopy(buffer, 0, copy, 0, size);
+ buffer = copy;
+ }
- _sendSocketAsyncEventArgs.SetBuffer(buffer, 0, size);
- _sendSocketAsyncEventArgs.RemoteEndPoint = NetworkManager.ToIPEndPoint(endPoint);
- _currentSendTaskCompletionSource = tcs;
+ cancellationToken.ThrowIfCancellationRequested();
- var willRaiseEvent = _Socket.SendAsync(_sendSocketAsyncEventArgs);
+ _Socket.SendTo(buffer, ipEndPoint);
+ return Task.FromResult(true);
+#else
+ var taskSource = new TaskCompletionSource<bool>();
- if (!willRaiseEvent)
+ try
{
- _sendSocketAsyncEventArgs_Completed(this, _sendSocketAsyncEventArgs);
+ _Socket.BeginSendTo(buffer, 0, size, SocketFlags.None, ipEndPoint, result =>
+ {
+ if (cancellationToken.IsCancellationRequested)
+ {
+ taskSource.TrySetCanceled();
+ return;
+ }
+ try
+ {
+ _Socket.EndSend(result);
+ taskSource.TrySetResult(true);
+ }
+ catch (Exception ex)
+ {
+ taskSource.TrySetException(ex);
+ }
+
+ }, null);
+ }
+ catch (Exception ex)
+ {
+ taskSource.TrySetException(ex);
}
- return tcs.Task;
+ return taskSource.Task;
+#endif
+ //ThrowIfDisposed();
+
+ //if (buffer == null) throw new ArgumentNullException("messageData");
+ //if (endPoint == null) throw new ArgumentNullException("endPoint");
+
+ //cancellationToken.ThrowIfCancellationRequested();
+
+ //var tcs = new TaskCompletionSource<int>();
+
+ //cancellationToken.Register(() => tcs.TrySetCanceled());
+
+ //_sendSocketAsyncEventArgs.SetBuffer(buffer, 0, size);
+ //_sendSocketAsyncEventArgs.RemoteEndPoint = NetworkManager.ToIPEndPoint(endPoint);
+ //_currentSendTaskCompletionSource = tcs;
+
+ //var willRaiseEvent = _Socket.SendAsync(_sendSocketAsyncEventArgs);
+
+ //if (!willRaiseEvent)
+ //{
+ // _sendSocketAsyncEventArgs_Completed(this, _sendSocketAsyncEventArgs);
+ //}
+
+ //return tcs.Task;
}
public async Task SendWithLockAsync(byte[] buffer, int size, IpEndPointInfo endPoint, CancellationToken cancellationToken)
{
ThrowIfDisposed();
- await _sendLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+ //await _sendLock.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
@@ -177,7 +237,7 @@ namespace Emby.Common.Implementations.Net
}
finally
{
- _sendLock.Release();
+ //_sendLock.Release();
}
}
@@ -213,5 +273,52 @@ namespace Emby.Common.Implementations.Net
return NetworkManager.ToIpEndPointInfo(endpoint);
}
+
+ private void ProcessResponse(IAsyncResult asyncResult)
+ {
+#if NET46
+ var state = asyncResult.AsyncState as AsyncReceiveState;
+ try
+ {
+ var bytesRead = state.Socket.EndReceiveFrom(asyncResult, ref state.RemoteEndPoint);
+
+ var ipEndPoint = state.RemoteEndPoint as IPEndPoint;
+ state.TaskCompletionSource.SetResult(
+ new SocketReceiveResult
+ {
+ Buffer = state.Buffer,
+ ReceivedBytes = bytesRead,
+ RemoteEndPoint = ToIpEndPointInfo(ipEndPoint),
+ LocalIPAddress = LocalIPAddress
+ }
+ );
+ }
+ catch (ObjectDisposedException)
+ {
+ state.TaskCompletionSource.SetCanceled();
+ }
+ catch (Exception ex)
+ {
+ state.TaskCompletionSource.SetException(ex);
+ }
+#endif
+ }
+
+ private class AsyncReceiveState
+ {
+ public AsyncReceiveState(Socket socket, EndPoint remoteEndPoint)
+ {
+ this.Socket = socket;
+ this.RemoteEndPoint = remoteEndPoint;
+ }
+
+ public EndPoint RemoteEndPoint;
+ public byte[] Buffer = new byte[8192];
+
+ public Socket Socket { get; private set; }
+
+ public TaskCompletionSource<SocketReceiveResult> TaskCompletionSource { get; set; }
+
+ }
}
}
diff --git a/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
index f841b8b6b..0a9c67285 100644
--- a/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
+++ b/Emby.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
@@ -677,20 +677,7 @@ namespace Emby.Server.Implementations.FileOrganization
var newPath = GetSeasonFolderPath(series, seasonNumber.Value, options);
- // MAX_PATH - trailing <NULL> charachter - drive component: 260 - 1 - 3 = 256
- // Usually newPath would include the drive component, but use 256 to be sure
- var maxFilenameLength = 256 - newPath.Length;
-
- if (!newPath.EndsWith(@"\"))
- {
- // Remove 1 for missing backslash combining path and filename
- maxFilenameLength--;
- }
-
- // Remove additional 4 chars to prevent PathTooLongException for downloaded subtitles (eg. filename.ext.eng.srt)
- maxFilenameLength -= 4;
-
- var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber.Value, episodeNumber.Value, endingEpisodeNumber, episodeName, options, maxFilenameLength);
+ var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber.Value, episodeNumber.Value, endingEpisodeNumber, episodeName, options);
if (string.IsNullOrEmpty(episodeFileName))
{
@@ -742,7 +729,7 @@ namespace Emby.Server.Implementations.FileOrganization
return Path.Combine(path, _fileSystem.GetValidFilename(seasonFolderName));
}
- private string GetEpisodeFileName(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, string episodeTitle, TvFileOrganizationOptions options, int? maxLength)
+ private string GetEpisodeFileName(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, string episodeTitle, TvFileOrganizationOptions options)
{
seriesName = _fileSystem.GetValidFilename(seriesName).Trim();
@@ -786,32 +773,15 @@ namespace Emby.Server.Implementations.FileOrganization
.Replace("%0e", episodeNumber.ToString("00", _usCulture))
.Replace("%00e", episodeNumber.ToString("000", _usCulture));
- if (maxLength.HasValue && result.Contains("%#"))
- {
- // Substract 3 for the temp token length (%#1, %#2 or %#3)
- int maxRemainingTitleLength = maxLength.Value - result.Length + 3;
- string shortenedEpisodeTitle = string.Empty;
-
- if (maxRemainingTitleLength > 5)
- {
- // A title with fewer than 5 letters wouldn't be of much value
- shortenedEpisodeTitle = episodeTitle.Substring(0, Math.Min(maxRemainingTitleLength, episodeTitle.Length));
- }
-
- result = result.Replace("%#1", shortenedEpisodeTitle)
- .Replace("%#2", shortenedEpisodeTitle.Replace(" ", "."))
- .Replace("%#3", shortenedEpisodeTitle.Replace(" ", "_"));
- }
-
- if (maxLength.HasValue && result.Length > maxLength.Value)
+ if (result.Contains("%#"))
{
- // There may be cases where reducing the title length may still not be sufficient to
- // stay below maxLength
- var msg = string.Format("Unable to generate an episode file name shorter than {0} characters to constrain to the max path limit", maxLength);
- throw new Exception(msg);
+ result = result.Replace("%#1", episodeTitle)
+ .Replace("%#2", episodeTitle.Replace(" ", "."))
+ .Replace("%#3", episodeTitle.Replace(" ", "_"));
}
- return result;
+ // Finally, call GetValidFilename again in case user customized the episode expression with any invalid filename characters
+ return _fileSystem.GetValidFilename(result).Trim();
}
private bool IsSameEpisode(string sourcePath, string newPath)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index 17c57712e..2fac96169 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -20,6 +20,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Net;
+using MediaBrowser.Model.System;
namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
@@ -30,8 +31,9 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
private readonly IServerApplicationHost _appHost;
private readonly ISocketFactory _socketFactory;
private readonly INetworkManager _networkManager;
+ private readonly IEnvironmentInfo _environment;
- public HdHomerunHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IHttpClient httpClient, IFileSystem fileSystem, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager)
+ public HdHomerunHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IHttpClient httpClient, IFileSystem fileSystem, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager, IEnvironmentInfo environment)
: base(config, logger, jsonSerializer, mediaEncoder)
{
_httpClient = httpClient;
@@ -39,6 +41,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
_appHost = appHost;
_socketFactory = socketFactory;
_networkManager = networkManager;
+ _environment = environment;
}
public string Name
@@ -503,11 +506,29 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
return new HdHomerunUdpStream(mediaSource, streamId, new LegacyHdHomerunChannelCommands(hdhomerunChannel.Url), modelInfo.TunerCount, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager);
}
- else
+
+ // The UDP method is not working reliably on OSX, and on BSD it hasn't been tested yet
+ var enableHttpStream = _environment.OperatingSystem == OperatingSystem.OSX ||
+ _environment.OperatingSystem == OperatingSystem.BSD;
+
+ if (enableHttpStream)
{
- //return new HdHomerunHttpStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost);
- return new HdHomerunUdpStream(mediaSource, streamId, new HdHomerunChannelCommands(hdhomerunChannel.Number), modelInfo.TunerCount, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager);
+ mediaSource.Protocol = MediaProtocol.Http;
+
+ var httpUrl = GetApiUrl(info, true) + "/auto/v" + hdhrId;
+
+ // If raw was used, the tuner doesn't support params
+ if (!string.IsNullOrWhiteSpace(profile)
+ && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase))
+ {
+ httpUrl += "?transcode=" + profile;
+ }
+ mediaSource.Path = httpUrl;
+
+ return new HdHomerunHttpStream(mediaSource, streamId, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost);
}
+
+ return new HdHomerunUdpStream(mediaSource, streamId, new HdHomerunChannelCommands(hdhomerunChannel.Number), modelInfo.TunerCount, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _socketFactory, _networkManager);
}
public async Task Validate(TunerHostInfo info)
diff --git a/SharedVersion.cs b/SharedVersion.cs
index f7f49dc75..d173d9ec5 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,3 +1,3 @@
using System.Reflection;
-[assembly: AssemblyVersion("3.2.8.14")]
+[assembly: AssemblyVersion("3.2.8.15")]