commit
93cbaaec66
|
@ -24,6 +24,7 @@ using MediaBrowser.Model.System;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
using Rssdp;
|
using Rssdp;
|
||||||
using Rssdp.Infrastructure;
|
using Rssdp.Infrastructure;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Emby.Dlna.Main
|
namespace Emby.Dlna.Main
|
||||||
{
|
{
|
||||||
|
@ -252,7 +253,7 @@ namespace Emby.Dlna.Main
|
||||||
var cacheLength = _config.GetDlnaConfiguration().BlastAliveMessageIntervalSeconds;
|
var cacheLength = _config.GetDlnaConfiguration().BlastAliveMessageIntervalSeconds;
|
||||||
_Publisher.SupportPnpRootDevice = false;
|
_Publisher.SupportPnpRootDevice = false;
|
||||||
|
|
||||||
var addresses = (await _appHost.GetLocalIpAddresses().ConfigureAwait(false)).ToList();
|
var addresses = (await _appHost.GetLocalIpAddresses(CancellationToken.None).ConfigureAwait(false)).ToList();
|
||||||
|
|
||||||
var udn = CreateUuid(_appHost.SystemId);
|
var udn = CreateUuid(_appHost.SystemId);
|
||||||
|
|
||||||
|
|
|
@ -831,7 +831,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
#region From XML
|
#region From XML
|
||||||
|
|
||||||
private async Task GetAVProtocolAsync()
|
private async Task GetAVProtocolAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
{
|
{
|
||||||
|
@ -845,12 +845,12 @@ namespace Emby.Dlna.PlayTo
|
||||||
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
|
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
|
||||||
|
|
||||||
var httpClient = new SsdpHttpClient(_httpClient, _config);
|
var httpClient = new SsdpHttpClient(_httpClient, _config);
|
||||||
var document = await httpClient.GetDataAsync(url).ConfigureAwait(false);
|
var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
AvCommands = TransportCommands.Create(document);
|
AvCommands = TransportCommands.Create(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task GetRenderingProtocolAsync()
|
private async Task GetRenderingProtocolAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
{
|
{
|
||||||
|
@ -864,7 +864,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
|
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
|
||||||
|
|
||||||
var httpClient = new SsdpHttpClient(_httpClient, _config);
|
var httpClient = new SsdpHttpClient(_httpClient, _config);
|
||||||
var document = await httpClient.GetDataAsync(url).ConfigureAwait(false);
|
var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
RendererCommands = TransportCommands.Create(document);
|
RendererCommands = TransportCommands.Create(document);
|
||||||
}
|
}
|
||||||
|
@ -897,11 +897,11 @@ namespace Emby.Dlna.PlayTo
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, IServerConfigurationManager config, ILogger logger, ITimerFactory timerFactory)
|
public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClient httpClient, IServerConfigurationManager config, ILogger logger, ITimerFactory timerFactory, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var ssdpHttpClient = new SsdpHttpClient(httpClient, config);
|
var ssdpHttpClient = new SsdpHttpClient(httpClient, config);
|
||||||
|
|
||||||
var document = await ssdpHttpClient.GetDataAsync(url.ToString()).ConfigureAwait(false);
|
var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var deviceProperties = new DeviceInfo();
|
var deviceProperties = new DeviceInfo();
|
||||||
|
|
||||||
|
@ -987,8 +987,8 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
if (device.GetAvTransportService() != null)
|
if (device.GetAvTransportService() != null)
|
||||||
{
|
{
|
||||||
await device.GetRenderingProtocolAsync().ConfigureAwait(false);
|
await device.GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
|
||||||
await device.GetAVProtocolAsync().ConfigureAwait(false);
|
await device.GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
|
|
|
@ -18,6 +18,7 @@ using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Globalization;
|
using MediaBrowser.Model.Globalization;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Emby.Dlna.PlayTo
|
namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
|
@ -44,6 +45,8 @@ namespace Emby.Dlna.PlayTo
|
||||||
private readonly List<string> _nonRendererUrls = new List<string>();
|
private readonly List<string> _nonRendererUrls = new List<string>();
|
||||||
private DateTime _lastRendererClear;
|
private DateTime _lastRendererClear;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
private SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1);
|
||||||
|
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory)
|
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory)
|
||||||
{
|
{
|
||||||
|
@ -98,9 +101,36 @@ namespace Emby.Dlna.PlayTo
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cancellationToken = _disposeCancellationTokenSource.Token;
|
||||||
|
|
||||||
|
await _sessionLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lock (_nonRendererUrls)
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await AddDevice(info, location, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error creating PlayTo device.", ex);
|
||||||
|
|
||||||
|
_nonRendererUrls.Add(location);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_sessionLock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AddDevice(UpnpDeviceInfo info, string location, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if ((DateTime.UtcNow - _lastRendererClear).TotalMinutes >= 10)
|
if ((DateTime.UtcNow - _lastRendererClear).TotalMinutes >= 10)
|
||||||
{
|
{
|
||||||
|
@ -112,47 +142,32 @@ namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var uri = info.Location;
|
var uri = info.Location;
|
||||||
_logger.Debug("Attempting to create PlayToController from location {0}", location);
|
_logger.Debug("Attempting to create PlayToController from location {0}", location);
|
||||||
var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, _timerFactory).ConfigureAwait(false);
|
var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger, _timerFactory, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (device.RendererCommands == null)
|
if (device.RendererCommands == null)
|
||||||
{
|
|
||||||
lock (_nonRendererUrls)
|
|
||||||
{
|
{
|
||||||
_nonRendererUrls.Add(location);
|
_nonRendererUrls.Add(location);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.Debug("Logging session activity from location {0}", location);
|
_logger.Debug("Logging session activity from location {0}", location);
|
||||||
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null)
|
var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null).ConfigureAwait(false);
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
var controller = sessionInfo.SessionController as PlayToController;
|
var controller = sessionInfo.SessionController as PlayToController;
|
||||||
|
|
||||||
if (controller == null)
|
if (controller == null)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string serverAddress;
|
string serverAddress;
|
||||||
if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Loopback))
|
if (info.LocalIpAddress == null || info.LocalIpAddress.Equals(IpAddressInfo.Any) || info.LocalIpAddress.Equals(IpAddressInfo.IPv6Loopback))
|
||||||
{
|
{
|
||||||
serverAddress = await GetServerAddress(null).ConfigureAwait(false);
|
serverAddress = await GetServerAddress(null, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
serverAddress = await GetServerAddress(info.LocalIpAddress).ConfigureAwait(false);
|
serverAddress = await GetServerAddress(info.LocalIpAddress, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
string accessToken = null;
|
string accessToken = null;
|
||||||
|
@ -203,22 +218,12 @@ namespace Emby.Dlna.PlayTo
|
||||||
_logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
|
_logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.ErrorException("Error creating PlayTo device.", ex);
|
|
||||||
|
|
||||||
lock (_nonRendererUrls)
|
private Task<string> GetServerAddress(IpAddressInfo address, CancellationToken cancellationToken)
|
||||||
{
|
|
||||||
_nonRendererUrls.Add(location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task<string> GetServerAddress(IpAddressInfo address)
|
|
||||||
{
|
{
|
||||||
if (address == null)
|
if (address == null)
|
||||||
{
|
{
|
||||||
return _appHost.GetLocalApiUrl();
|
return _appHost.GetLocalApiUrl(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Task.FromResult(_appHost.GetLocalApiUrl(address));
|
return Task.FromResult(_appHost.GetLocalApiUrl(address));
|
||||||
|
@ -226,6 +231,15 @@ namespace Emby.Dlna.PlayTo
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_disposeCancellationTokenSource.Cancel();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
_deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered;
|
_deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered;
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Emby.Dlna.PlayTo
|
namespace Emby.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
|
@ -89,7 +90,7 @@ namespace Emby.Dlna.PlayTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<XDocument> GetDataAsync(string url)
|
public async Task<XDocument> GetDataAsync(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var options = new HttpRequestOptions
|
var options = new HttpRequestOptions
|
||||||
{
|
{
|
||||||
|
@ -99,7 +100,9 @@ namespace Emby.Dlna.PlayTo
|
||||||
BufferContent = false,
|
BufferContent = false,
|
||||||
|
|
||||||
// The periodic requests may keep some devices awake
|
// The periodic requests may keep some devices awake
|
||||||
LogRequestAsDebug = true
|
LogRequestAsDebug = true,
|
||||||
|
|
||||||
|
CancellationToken = cancellationToken
|
||||||
};
|
};
|
||||||
|
|
||||||
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
|
options.RequestHeaders["FriendlyName.DLNA.ORG"] = FriendlyName;
|
||||||
|
|
|
@ -1901,9 +1901,9 @@ namespace Emby.Server.Implementations
|
||||||
/// Gets the system status.
|
/// Gets the system status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>SystemInfo.</returns>
|
/// <returns>SystemInfo.</returns>
|
||||||
public async Task<SystemInfo> GetSystemInfo()
|
public async Task<SystemInfo> GetSystemInfo(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var localAddress = await GetLocalApiUrl().ConfigureAwait(false);
|
var localAddress = await GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
return new SystemInfo
|
return new SystemInfo
|
||||||
{
|
{
|
||||||
|
@ -1955,12 +1955,12 @@ namespace Emby.Server.Implementations
|
||||||
get { return Certificate != null || ServerConfigurationManager.Configuration.IsBehindProxy; }
|
get { return Certificate != null || ServerConfigurationManager.Configuration.IsBehindProxy; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GetLocalApiUrl()
|
public async Task<string> GetLocalApiUrl(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Return the first matched address, if found, or the first known local address
|
// Return the first matched address, if found, or the first known local address
|
||||||
var address = (await GetLocalIpAddresses().ConfigureAwait(false)).FirstOrDefault(i => !i.Equals(IpAddressInfo.Loopback) && !i.Equals(IpAddressInfo.IPv6Loopback));
|
var address = (await GetLocalIpAddresses(cancellationToken).ConfigureAwait(false)).FirstOrDefault(i => !i.Equals(IpAddressInfo.Loopback) && !i.Equals(IpAddressInfo.IPv6Loopback));
|
||||||
|
|
||||||
if (address != null)
|
if (address != null)
|
||||||
{
|
{
|
||||||
|
@ -1994,7 +1994,7 @@ namespace Emby.Server.Implementations
|
||||||
HttpPort.ToString(CultureInfo.InvariantCulture));
|
HttpPort.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<IpAddressInfo>> GetLocalIpAddresses()
|
public async Task<List<IpAddressInfo>> GetLocalIpAddresses(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var addresses = ServerConfigurationManager
|
var addresses = ServerConfigurationManager
|
||||||
.Configuration
|
.Configuration
|
||||||
|
@ -2011,7 +2011,7 @@ namespace Emby.Server.Implementations
|
||||||
|
|
||||||
foreach (var address in addresses)
|
foreach (var address in addresses)
|
||||||
{
|
{
|
||||||
var valid = await IsIpAddressValidAsync(address).ConfigureAwait(false);
|
var valid = await IsIpAddressValidAsync(address, cancellationToken).ConfigureAwait(false);
|
||||||
if (valid)
|
if (valid)
|
||||||
{
|
{
|
||||||
list.Add(address);
|
list.Add(address);
|
||||||
|
@ -2043,7 +2043,7 @@ namespace Emby.Server.Implementations
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
||||||
private DateTime _lastAddressCacheClear;
|
private DateTime _lastAddressCacheClear;
|
||||||
private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address)
|
private async Task<bool> IsIpAddressValidAsync(IpAddressInfo address, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (address.Equals(IpAddressInfo.Loopback) ||
|
if (address.Equals(IpAddressInfo.Loopback) ||
|
||||||
address.Equals(IpAddressInfo.IPv6Loopback))
|
address.Equals(IpAddressInfo.IPv6Loopback))
|
||||||
|
@ -2075,7 +2075,9 @@ namespace Emby.Server.Implementations
|
||||||
LogErrors = false,
|
LogErrors = false,
|
||||||
LogRequest = false,
|
LogRequest = false,
|
||||||
TimeoutMs = 30000,
|
TimeoutMs = 30000,
|
||||||
BufferContent = false
|
BufferContent = false,
|
||||||
|
|
||||||
|
CancellationToken = cancellationToken
|
||||||
|
|
||||||
}, "POST").ConfigureAwait(false))
|
}, "POST").ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
@ -2090,6 +2092,10 @@ namespace Emby.Server.Implementations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
//Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false);
|
//Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false);
|
||||||
|
|
|
@ -13,6 +13,7 @@ using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
using Mono.Nat;
|
using Mono.Nat;
|
||||||
using MediaBrowser.Model.Extensions;
|
using MediaBrowser.Model.Extensions;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.EntryPoints
|
namespace Emby.Server.Implementations.EntryPoints
|
||||||
{
|
{
|
||||||
|
@ -158,7 +159,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var localAddressString = await _appHost.GetLocalApiUrl().ConfigureAwait(false);
|
var localAddressString = await _appHost.GetLocalApiUrl(CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
Uri uri;
|
Uri uri;
|
||||||
if (Uri.TryCreate(localAddressString, UriKind.Absolute, out uri))
|
if (Uri.TryCreate(localAddressString, UriKind.Absolute, out uri))
|
||||||
|
|
|
@ -191,7 +191,8 @@ namespace Emby.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
ItemFields.AirTime,
|
ItemFields.AirTime,
|
||||||
ItemFields.DateCreated,
|
ItemFields.DateCreated,
|
||||||
ItemFields.ChannelInfo
|
ItemFields.ChannelInfo,
|
||||||
|
ItemFields.ParentId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -815,7 +815,7 @@ namespace Emby.Server.Implementations.Library
|
||||||
|
|
||||||
var text = new StringBuilder();
|
var text = new StringBuilder();
|
||||||
|
|
||||||
var localAddress = _appHost.GetLocalApiUrl().Result ?? string.Empty;
|
var localAddress = _appHost.GetLocalApiUrl(CancellationToken.None).Result ?? string.Empty;
|
||||||
|
|
||||||
text.AppendLine("Use your web browser to visit:");
|
text.AppendLine("Use your web browser to visit:");
|
||||||
text.AppendLine(string.Empty);
|
text.AppendLine(string.Empty);
|
||||||
|
|
|
@ -95,7 +95,7 @@ namespace Emby.Server.Implementations.LiveTv
|
||||||
}
|
}
|
||||||
|
|
||||||
var list = sources.ToList();
|
var list = sources.ToList();
|
||||||
var serverUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false);
|
var serverUrl = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
foreach (var source in list)
|
foreach (var source in list)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,6 +11,7 @@ using MediaBrowser.Model.Extensions;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Networking
|
namespace Emby.Server.Implementations.Networking
|
||||||
{
|
{
|
||||||
|
@ -37,7 +38,7 @@ namespace Emby.Server.Implementations.Networking
|
||||||
|
|
||||||
if (_localIpAddresses == null || forceRefresh)
|
if (_localIpAddresses == null || forceRefresh)
|
||||||
{
|
{
|
||||||
var addresses = GetLocalIpAddressesInternal().Select(ToIpAddressInfo).ToList();
|
var addresses = GetLocalIpAddressesInternal().Result.Select(ToIpAddressInfo).ToList();
|
||||||
|
|
||||||
_localIpAddresses = addresses;
|
_localIpAddresses = addresses;
|
||||||
_lastRefresh = DateTime.UtcNow;
|
_lastRefresh = DateTime.UtcNow;
|
||||||
|
@ -49,14 +50,14 @@ namespace Emby.Server.Implementations.Networking
|
||||||
return _localIpAddresses;
|
return _localIpAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<IPAddress> GetLocalIpAddressesInternal()
|
private async Task<List<IPAddress>> GetLocalIpAddressesInternal()
|
||||||
{
|
{
|
||||||
var list = GetIPsDefault()
|
var list = GetIPsDefault()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (list.Count == 0)
|
if (list.Count == 0)
|
||||||
{
|
{
|
||||||
list.AddRange(GetLocalIpAddressesFallback().Result);
|
list.AddRange(await GetLocalIpAddressesFallback().ConfigureAwait(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
var listClone = list.ToList();
|
var listClone = list.ToList();
|
||||||
|
@ -65,7 +66,8 @@ namespace Emby.Server.Implementations.Networking
|
||||||
.OrderBy(i => i.AddressFamily == AddressFamily.InterNetwork ? 0 : 1)
|
.OrderBy(i => i.AddressFamily == AddressFamily.InterNetwork ? 0 : 1)
|
||||||
.ThenBy(i => listClone.IndexOf(i))
|
.ThenBy(i => listClone.IndexOf(i))
|
||||||
.Where(FilterIpAddress)
|
.Where(FilterIpAddress)
|
||||||
.DistinctBy(i => i.ToString());
|
.DistinctBy(i => i.ToString())
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool FilterIpAddress(IPAddress address)
|
private bool FilterIpAddress(IPAddress address)
|
||||||
|
|
|
@ -1182,7 +1182,7 @@ namespace Emby.Server.Implementations.Session
|
||||||
{
|
{
|
||||||
var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList();
|
var sessions = Sessions.Where(i => i.IsActive && i.SessionController != null).ToList();
|
||||||
|
|
||||||
var info = await _appHost.GetSystemInfo().ConfigureAwait(false);
|
var info = await _appHost.GetSystemInfo(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var tasks = sessions.Select(session => Task.Run(async () =>
|
var tasks = sessions.Select(session => Task.Run(async () =>
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Model.Social;
|
using MediaBrowser.Model.Social;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Emby.Server.Implementations.Social
|
namespace Emby.Server.Implementations.Social
|
||||||
|
@ -42,7 +43,7 @@ namespace Emby.Server.Implementations.Social
|
||||||
throw new ResourceNotFoundException();
|
throw new ResourceNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
var externalUrl = (await _appHost.GetSystemInfo().ConfigureAwait(false)).WanAddress;
|
var externalUrl = (await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false)).WanAddress;
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(externalUrl))
|
if (string.IsNullOrWhiteSpace(externalUrl))
|
||||||
{
|
{
|
||||||
|
@ -73,7 +74,7 @@ namespace Emby.Server.Implementations.Social
|
||||||
{
|
{
|
||||||
var info = _repository.GetShareInfo(id);
|
var info = _repository.GetShareInfo(id);
|
||||||
|
|
||||||
AddShareInfo(info, _appHost.GetSystemInfo().Result.WanAddress);
|
AddShareInfo(info, _appHost.GetSystemInfo(CancellationToken.None).Result.WanAddress);
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Udp
|
||||||
|
|
||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
|
|
||||||
private readonly List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, Task>>> _responders = new List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, Task>>>();
|
private readonly List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>> _responders = new List<Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>>();
|
||||||
|
|
||||||
private readonly IServerApplicationHost _appHost;
|
private readonly IServerApplicationHost _appHost;
|
||||||
private readonly IJsonSerializer _json;
|
private readonly IJsonSerializer _json;
|
||||||
|
@ -44,9 +44,9 @@ namespace Emby.Server.Implementations.Udp
|
||||||
AddMessageResponder("who is MediaBrowserServer_v2?", false, RespondToV2Message);
|
AddMessageResponder("who is MediaBrowserServer_v2?", false, RespondToV2Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddMessageResponder(string message, bool isSubstring, Func<string, IpEndPointInfo, Encoding, Task> responder)
|
private void AddMessageResponder(string message, bool isSubstring, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task> responder)
|
||||||
{
|
{
|
||||||
_responders.Add(new Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, Task>>(message, isSubstring, responder));
|
_responders.Add(new Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>(message, isSubstring, responder));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -67,9 +67,15 @@ namespace Emby.Server.Implementations.Udp
|
||||||
|
|
||||||
if (responder != null)
|
if (responder != null)
|
||||||
{
|
{
|
||||||
|
var cancellationToken = CancellationToken.None;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await responder.Item2.Item3(responder.Item1, message.RemoteEndPoint, encoding).ConfigureAwait(false);
|
await responder.Item2.Item3(responder.Item1, message.RemoteEndPoint, encoding, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -78,7 +84,7 @@ namespace Emby.Server.Implementations.Udp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, Task>>> GetResponder(byte[] buffer, int bytesReceived, Encoding encoding)
|
private Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>> GetResponder(byte[] buffer, int bytesReceived, Encoding encoding)
|
||||||
{
|
{
|
||||||
var text = encoding.GetString(buffer, 0, bytesReceived);
|
var text = encoding.GetString(buffer, 0, bytesReceived);
|
||||||
var responder = _responders.FirstOrDefault(i =>
|
var responder = _responders.FirstOrDefault(i =>
|
||||||
|
@ -94,14 +100,14 @@ namespace Emby.Server.Implementations.Udp
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, Task>>>(text, responder);
|
return new Tuple<string, Tuple<string, bool, Func<string, IpEndPointInfo, Encoding, CancellationToken, Task>>>(text, responder);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RespondToV2Message(string messageText, IpEndPointInfo endpoint, Encoding encoding)
|
private async Task RespondToV2Message(string messageText, IpEndPointInfo endpoint, Encoding encoding, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var parts = messageText.Split('|');
|
var parts = messageText.Split('|');
|
||||||
|
|
||||||
var localUrl = await _appHost.GetLocalApiUrl().ConfigureAwait(false);
|
var localUrl = await _appHost.GetLocalApiUrl(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(localUrl))
|
if (!string.IsNullOrEmpty(localUrl))
|
||||||
{
|
{
|
||||||
|
@ -112,7 +118,7 @@ namespace Emby.Server.Implementations.Udp
|
||||||
Name = _appHost.FriendlyName
|
Name = _appHost.FriendlyName
|
||||||
};
|
};
|
||||||
|
|
||||||
await SendAsync(encoding.GetBytes(_json.SerializeToString(response)), endpoint).ConfigureAwait(false);
|
await SendAsync(encoding.GetBytes(_json.SerializeToString(response)), endpoint, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (parts.Length > 1)
|
if (parts.Length > 1)
|
||||||
{
|
{
|
||||||
|
@ -248,7 +254,7 @@ namespace Emby.Server.Implementations.Udp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendAsync(byte[] bytes, IpEndPointInfo remoteEndPoint)
|
public async Task SendAsync(byte[] bytes, IpEndPointInfo remoteEndPoint, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (_isDisposed)
|
if (_isDisposed)
|
||||||
{
|
{
|
||||||
|
@ -267,7 +273,7 @@ namespace Emby.Server.Implementations.Udp
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _udpClient.SendToAsync(bytes, 0, bytes.Length, remoteEndPoint, CancellationToken.None).ConfigureAwait(false);
|
await _udpClient.SendToAsync(bytes, 0, bytes.Length, remoteEndPoint, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
_logger.Info("Udp message sent to {0}", remoteEndPoint);
|
_logger.Info("Udp message sent to {0}", remoteEndPoint);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,10 @@ using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.ScheduledTasks
|
namespace MediaBrowser.Api.ScheduledTasks
|
||||||
{
|
{
|
||||||
|
@ -63,7 +64,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The state.</param>
|
/// <param name="state">The state.</param>
|
||||||
/// <returns>Task{IEnumerable{TaskInfo}}.</returns>
|
/// <returns>Task{IEnumerable{TaskInfo}}.</returns>
|
||||||
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(WebSocketListenerState state)
|
protected override Task<IEnumerable<TaskInfo>> GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return Task.FromResult(TaskManager.ScheduledTasks
|
return Task.FromResult(TaskManager.ScheduledTasks
|
||||||
.OrderBy(i => i.Name)
|
.OrderBy(i => i.Name)
|
||||||
|
|
|
@ -248,9 +248,20 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
if (song != null)
|
if (song != null)
|
||||||
{
|
{
|
||||||
result.Album = song.Album;
|
|
||||||
result.AlbumArtist = song.AlbumArtists.FirstOrDefault();
|
result.AlbumArtist = song.AlbumArtists.FirstOrDefault();
|
||||||
result.Artists = song.Artists;
|
result.Artists = song.Artists;
|
||||||
|
|
||||||
|
album = song.AlbumEntity;
|
||||||
|
|
||||||
|
if (album != null)
|
||||||
|
{
|
||||||
|
result.Album = album.Name;
|
||||||
|
result.AlbumId = album.Id.ToString("N");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Album = song.Album;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(item.ChannelId))
|
if (!string.IsNullOrWhiteSpace(item.ChannelId))
|
||||||
|
|
|
@ -5,8 +5,9 @@ using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Session;
|
using MediaBrowser.Model.Session;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Session
|
namespace MediaBrowser.Api.Session
|
||||||
{
|
{
|
||||||
|
@ -86,7 +87,7 @@ namespace MediaBrowser.Api.Session
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The state.</param>
|
/// <param name="state">The state.</param>
|
||||||
/// <returns>Task{SystemInfo}.</returns>
|
/// <returns>Task{SystemInfo}.</returns>
|
||||||
protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(WebSocketListenerState state)
|
protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto));
|
return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto));
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.System
|
namespace MediaBrowser.Api.System
|
||||||
{
|
{
|
||||||
|
@ -43,7 +44,7 @@ namespace MediaBrowser.Api.System
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The state.</param>
|
/// <param name="state">The state.</param>
|
||||||
/// <returns>Task{SystemInfo}.</returns>
|
/// <returns>Task{SystemInfo}.</returns>
|
||||||
protected override Task<List<ActivityLogEntry>> GetDataToSend(WebSocketListenerState state)
|
protected override Task<List<ActivityLogEntry>> GetDataToSend(WebSocketListenerState state, CancellationToken CancellationToken)
|
||||||
{
|
{
|
||||||
return Task.FromResult(new List<ActivityLogEntry>());
|
return Task.FromResult(new List<ActivityLogEntry>());
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.System;
|
using MediaBrowser.Model.System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Threading;
|
using MediaBrowser.Model.Threading;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.System
|
namespace MediaBrowser.Api.System
|
||||||
{
|
{
|
||||||
|
@ -40,9 +41,9 @@ namespace MediaBrowser.Api.System
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The state.</param>
|
/// <param name="state">The state.</param>
|
||||||
/// <returns>Task{SystemInfo}.</returns>
|
/// <returns>Task{SystemInfo}.</returns>
|
||||||
protected override Task<SystemInfo> GetDataToSend(WebSocketListenerState state)
|
protected override Task<SystemInfo> GetDataToSend(WebSocketListenerState state, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
return _appHost.GetSystemInfo();
|
return _appHost.GetSystemInfo(cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ using MediaBrowser.Controller.IO;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Services;
|
using MediaBrowser.Model.Services;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.System
|
namespace MediaBrowser.Api.System
|
||||||
{
|
{
|
||||||
|
@ -164,14 +165,14 @@ namespace MediaBrowser.Api.System
|
||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public async Task<object> Get(GetSystemInfo request)
|
public async Task<object> Get(GetSystemInfo request)
|
||||||
{
|
{
|
||||||
var result = await _appHost.GetSystemInfo().ConfigureAwait(false);
|
var result = await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetPublicSystemInfo request)
|
public async Task<object> Get(GetPublicSystemInfo request)
|
||||||
{
|
{
|
||||||
var result = await _appHost.GetSystemInfo().ConfigureAwait(false);
|
var result = await _appHost.GetSystemInfo(CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
var publicInfo = new PublicSystemInfo
|
var publicInfo = new PublicSystemInfo
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Model.Net;
|
using MediaBrowser.Model.Net;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller
|
namespace MediaBrowser.Controller
|
||||||
{
|
{
|
||||||
|
@ -19,7 +20,7 @@ namespace MediaBrowser.Controller
|
||||||
/// Gets the system info.
|
/// Gets the system info.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>SystemInfo.</returns>
|
/// <returns>SystemInfo.</returns>
|
||||||
Task<SystemInfo> GetSystemInfo();
|
Task<SystemInfo> GetSystemInfo(CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether [supports automatic run at startup].
|
/// Gets a value indicating whether [supports automatic run at startup].
|
||||||
|
@ -61,13 +62,13 @@ namespace MediaBrowser.Controller
|
||||||
/// Gets the local ip address.
|
/// Gets the local ip address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The local ip address.</value>
|
/// <value>The local ip address.</value>
|
||||||
Task<List<IpAddressInfo>> GetLocalIpAddresses();
|
Task<List<IpAddressInfo>> GetLocalIpAddresses(CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the local API URL.
|
/// Gets the local API URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The local API URL.</value>
|
/// <value>The local API URL.</value>
|
||||||
Task<string> GetLocalApiUrl();
|
Task<string> GetLocalApiUrl(CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the local API URL.
|
/// Gets the local API URL.
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace MediaBrowser.Controller.Net
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The state.</param>
|
/// <param name="state">The state.</param>
|
||||||
/// <returns>Task{`1}.</returns>
|
/// <returns>Task{`1}.</returns>
|
||||||
protected abstract Task<TReturnDataType> GetDataToSend(TStateType state);
|
protected abstract Task<TReturnDataType> GetDataToSend(TStateType state, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The logger
|
/// The logger
|
||||||
|
@ -209,7 +209,9 @@ namespace MediaBrowser.Controller.Net
|
||||||
{
|
{
|
||||||
var state = tuple.Item4;
|
var state = tuple.Item4;
|
||||||
|
|
||||||
var data = await GetDataToSend(state).ConfigureAwait(false);
|
var cancellationToken = tuple.Item2.Token;
|
||||||
|
|
||||||
|
var data = await GetDataToSend(state, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
|
@ -218,7 +220,7 @@ namespace MediaBrowser.Controller.Net
|
||||||
MessageType = Name,
|
MessageType = Name,
|
||||||
Data = data
|
Data = data
|
||||||
|
|
||||||
}, tuple.Item2.Token).ConfigureAwait(false);
|
}, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
state.DateLastSendUtc = DateTime.UtcNow;
|
state.DateLastSendUtc = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace MediaBrowser.Controller.Sync
|
||||||
/// Gets the jobs.
|
/// Gets the jobs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>QueryResult<SyncJob>.</returns>
|
/// <returns>QueryResult<SyncJob>.</returns>
|
||||||
Task<QueryResult<SyncJob>> GetJobs(SyncJobQuery query);
|
QueryResult<SyncJob> GetJobs(SyncJobQuery query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the job items.
|
/// Gets the job items.
|
||||||
|
|
|
@ -1343,7 +1343,7 @@ namespace MediaBrowser.Model.Dlna
|
||||||
|
|
||||||
if (itemBitrate > requestedMaxBitrate)
|
if (itemBitrate > requestedMaxBitrate)
|
||||||
{
|
{
|
||||||
_logger.Info("Bitrate exceeds " + playMethod + " limit: media bitrate: {0}, max bitrate: {1}", item.Bitrate.Value.ToString(CultureInfo.InvariantCulture), requestedMaxBitrate.ToString(CultureInfo.InvariantCulture));
|
_logger.Info("Bitrate exceeds " + playMethod + " limit: media bitrate: {0}, max bitrate: {1}", itemBitrate.ToString(CultureInfo.InvariantCulture), requestedMaxBitrate.ToString(CultureInfo.InvariantCulture));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,7 @@ namespace MediaBrowser.Model.Search
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The album.</value>
|
/// <value>The album.</value>
|
||||||
public string Album { get; set; }
|
public string Album { get; set; }
|
||||||
|
public string AlbumId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the album artist.
|
/// Gets or sets the album artist.
|
||||||
|
|
|
@ -200,7 +200,16 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
sb.Append("<link rel=\"manifest\" href=\"manifest.json\">");
|
sb.Append("<link rel=\"manifest\" href=\"manifest.json\">");
|
||||||
sb.Append("<meta name=\"format-detection\" content=\"telephone=no\">");
|
sb.Append("<meta name=\"format-detection\" content=\"telephone=no\">");
|
||||||
sb.Append("<meta name=\"msapplication-tap-highlight\" content=\"no\">");
|
sb.Append("<meta name=\"msapplication-tap-highlight\" content=\"no\">");
|
||||||
sb.Append("<meta name=\"viewport\" content=\"user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width\">");
|
|
||||||
|
if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
sb.Append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no\">");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1\">");
|
||||||
|
}
|
||||||
|
|
||||||
sb.Append("<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">");
|
sb.Append("<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">");
|
||||||
sb.Append("<meta name=\"mobile-web-app-capable\" content=\"yes\">");
|
sb.Append("<meta name=\"mobile-web-app-capable\" content=\"yes\">");
|
||||||
sb.Append("<meta name=\"application-name\" content=\"Emby\">");
|
sb.Append("<meta name=\"application-name\" content=\"Emby\">");
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("3.2.40.1")]
|
[assembly: AssemblyVersion("3.2.40.2")]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user