diff options
| author | Cody Robibero <cody@robibe.ro> | 2023-11-09 22:03:55 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-09 22:03:55 -0700 |
| commit | 892973a9e372000ad7babe2381e4e83b39591951 (patch) | |
| tree | fc408136c09e6377309629ad6b2d4b2b26ff3c3f /Emby.Dlna | |
| parent | 35bd0c00c965176d6ddb167605ed3a3eba9a4524 (diff) | |
| parent | 44b771bfb4b6412360b18c80621c90902c0a43a7 (diff) | |
Merge branch 'master' into media-type
Diffstat (limited to 'Emby.Dlna')
| -rw-r--r-- | Emby.Dlna/ContentDirectory/ControlHandler.cs | 52 | ||||
| -rw-r--r-- | Emby.Dlna/Emby.Dlna.csproj | 6 | ||||
| -rw-r--r-- | Emby.Dlna/Extensions/DlnaServiceCollectionExtensions.cs | 69 | ||||
| -rw-r--r-- | Emby.Dlna/Main/DlnaEntryPoint.cs | 134 | ||||
| -rw-r--r-- | Emby.Dlna/PlayTo/Device.cs | 17 | ||||
| -rw-r--r-- | Emby.Dlna/PlayTo/DlnaHttpClient.cs | 55 | ||||
| -rw-r--r-- | Emby.Dlna/PlayTo/PlayToController.cs | 13 | ||||
| -rw-r--r-- | Emby.Dlna/PlayTo/PlayToManager.cs | 4 |
8 files changed, 153 insertions, 197 deletions
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 12cd7e2ef7..99068826d9 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -565,30 +565,18 @@ namespace Emby.Dlna.ContentDirectory if (stubType != StubType.Folder && item is IHasCollectionType collectionFolder) { - var collectionType = collectionFolder.CollectionType; - if (string.Equals(CollectionType.Music, collectionType, StringComparison.OrdinalIgnoreCase)) + switch (collectionFolder.CollectionType) { - return GetMusicFolders(item, user, stubType, sort, startIndex, limit); - } - - if (string.Equals(CollectionType.Movies, collectionType, StringComparison.OrdinalIgnoreCase)) - { - return GetMovieFolders(item, user, stubType, sort, startIndex, limit); - } - - if (string.Equals(CollectionType.TvShows, collectionType, StringComparison.OrdinalIgnoreCase)) - { - return GetTvFolders(item, user, stubType, sort, startIndex, limit); - } - - if (string.Equals(CollectionType.Folders, collectionType, StringComparison.OrdinalIgnoreCase)) - { - return GetFolders(user, startIndex, limit); - } - - if (string.Equals(CollectionType.LiveTv, collectionType, StringComparison.OrdinalIgnoreCase)) - { - return GetLiveTvChannels(user, sort, startIndex, limit); + case CollectionType.Music: + return GetMusicFolders(item, user, stubType, sort, startIndex, limit); + case CollectionType.Movies: + return GetMovieFolders(item, user, stubType, sort, startIndex, limit); + case CollectionType.TvShows: + return GetTvFolders(item, user, stubType, sort, startIndex, limit); + case CollectionType.Folders: + return GetFolders(user, startIndex, limit); + case CollectionType.LiveTv: + return GetLiveTvChannels(user, sort, startIndex, limit); } } @@ -917,7 +905,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult<ServerItem> GetGenres(BaseItem parent, InternalItemsQuery query) { // Don't sort - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); query.AncestorIds = new[] { parent.Id }; var genresResult = _libraryManager.GetGenres(query); @@ -933,7 +921,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult<ServerItem> GetMusicGenres(BaseItem parent, InternalItemsQuery query) { // Don't sort - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); query.AncestorIds = new[] { parent.Id }; var genresResult = _libraryManager.GetMusicGenres(query); @@ -949,7 +937,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult<ServerItem> GetMusicAlbumArtists(BaseItem parent, InternalItemsQuery query) { // Don't sort - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); query.AncestorIds = new[] { parent.Id }; var artists = _libraryManager.GetAlbumArtists(query); @@ -965,7 +953,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult<ServerItem> GetMusicArtists(BaseItem parent, InternalItemsQuery query) { // Don't sort - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); query.AncestorIds = new[] { parent.Id }; var artists = _libraryManager.GetArtists(query); return ToResult(query.StartIndex, artists); @@ -980,7 +968,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult<ServerItem> GetFavoriteArtists(BaseItem parent, InternalItemsQuery query) { // Don't sort - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); query.AncestorIds = new[] { parent.Id }; query.IsFavorite = true; var artists = _libraryManager.GetArtists(query); @@ -1011,7 +999,7 @@ namespace Emby.Dlna.ContentDirectory /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> private QueryResult<ServerItem> GetNextUp(BaseItem parent, InternalItemsQuery query) { - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); var result = _tvSeriesManager.GetNextUp( new NextUpQuery @@ -1036,7 +1024,7 @@ namespace Emby.Dlna.ContentDirectory /// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns> private QueryResult<ServerItem> GetLatest(BaseItem parent, InternalItemsQuery query, BaseItemKind itemType) { - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); var items = _userViewManager.GetLatestItems( new LatestItemsQuery @@ -1203,9 +1191,9 @@ namespace Emby.Dlna.ContentDirectory /// </summary> /// <param name="sort">The <see cref="SortCriteria"/>.</param> /// <param name="isPreSorted">True if pre-sorted.</param> - private static (string SortName, SortOrder SortOrder)[] GetOrderBy(SortCriteria sort, bool isPreSorted) + private static (ItemSortBy SortName, SortOrder SortOrder)[] GetOrderBy(SortCriteria sort, bool isPreSorted) { - return isPreSorted ? Array.Empty<(string, SortOrder)>() : new[] { (ItemSortBy.SortName, sort.SortOrder) }; + return isPreSorted ? Array.Empty<(ItemSortBy, SortOrder)>() : new[] { (ItemSortBy.SortName, sort.SortOrder) }; } /// <summary> diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index aca2399644..efbef05640 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -26,8 +26,12 @@ <CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors> </PropertyGroup> - <!-- Code Analyzers--> + <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> + <PackageReference Include="IDisposableAnalyzers"> + <PrivateAssets>all</PrivateAssets> + <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> + </PackageReference> <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> diff --git a/Emby.Dlna/Extensions/DlnaServiceCollectionExtensions.cs b/Emby.Dlna/Extensions/DlnaServiceCollectionExtensions.cs new file mode 100644 index 0000000000..87ec14d958 --- /dev/null +++ b/Emby.Dlna/Extensions/DlnaServiceCollectionExtensions.cs @@ -0,0 +1,69 @@ +using System; +using System.Globalization; +using System.Net; +using System.Net.Http; +using System.Text; +using Emby.Dlna.ConnectionManager; +using Emby.Dlna.ContentDirectory; +using Emby.Dlna.MediaReceiverRegistrar; +using Emby.Dlna.Ssdp; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller; +using MediaBrowser.Controller.Dlna; +using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Net; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Rssdp.Infrastructure; + +namespace Emby.Dlna.Extensions; + +/// <summary> +/// Extension methods for adding DLNA services. +/// </summary> +public static class DlnaServiceCollectionExtensions +{ + /// <summary> + /// Adds DLNA services to the provided <see cref="IServiceCollection"/>. + /// </summary> + /// <param name="services">The <see cref="IServiceCollection"/>.</param> + /// <param name="applicationHost">The <see cref="IServerApplicationHost"/>.</param> + public static void AddDlnaServices( + this IServiceCollection services, + IServerApplicationHost applicationHost) + { + services.AddHttpClient(NamedClient.Dlna, c => + { + c.DefaultRequestHeaders.UserAgent.ParseAdd( + string.Format( + CultureInfo.InvariantCulture, + "{0}/{1} UPnP/1.0 {2}/{3}", + Environment.OSVersion.Platform, + Environment.OSVersion, + applicationHost.Name, + applicationHost.ApplicationVersionString)); + + c.DefaultRequestHeaders.Add("CPFN.UPNP.ORG", applicationHost.FriendlyName); // Required for UPnP DeviceArchitecture v2.0 + c.DefaultRequestHeaders.Add("FriendlyName.DLNA.ORG", applicationHost.FriendlyName); // REVIEW: where does this come from? + }) + .ConfigurePrimaryHttpMessageHandler(_ => new SocketsHttpHandler + { + AutomaticDecompression = DecompressionMethods.All, + RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8 + }); + + services.AddSingleton<IDlnaManager, DlnaManager>(); + services.AddSingleton<IDeviceDiscovery, DeviceDiscovery>(); + services.AddSingleton<IContentDirectory, ContentDirectoryService>(); + services.AddSingleton<IConnectionManager, ConnectionManagerService>(); + services.AddSingleton<IMediaReceiverRegistrar, MediaReceiverRegistrarService>(); + + services.AddSingleton<ISsdpCommunicationsServer>(provider => new SsdpCommunicationsServer( + provider.GetRequiredService<ISocketFactory>(), + provider.GetRequiredService<INetworkManager>(), + provider.GetRequiredService<ILogger<SsdpCommunicationsServer>>()) + { + IsShared = true + }); + } +} diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 1a4bec398c..aa70124870 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -23,10 +23,8 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; -using MediaBrowser.Controller.TV; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.Net; using Microsoft.Extensions.Logging; using Rssdp; using Rssdp.Infrastructure; @@ -49,14 +47,13 @@ namespace Emby.Dlna.Main private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaEncoder _mediaEncoder; private readonly IDeviceDiscovery _deviceDiscovery; - private readonly ISocketFactory _socketFactory; + private readonly ISsdpCommunicationsServer _communicationsServer; private readonly INetworkManager _networkManager; - private readonly object _syncLock = new object(); + private readonly object _syncLock = new(); private readonly bool _disabled; private PlayToManager _manager; private SsdpDevicePublisher _publisher; - private ISsdpCommunicationsServer _communicationsServer; private bool _disposed; @@ -75,10 +72,8 @@ namespace Emby.Dlna.Main IMediaSourceManager mediaSourceManager, IDeviceDiscovery deviceDiscovery, IMediaEncoder mediaEncoder, - ISocketFactory socketFactory, - INetworkManager networkManager, - IUserViewManager userViewManager, - ITVSeriesManager tvSeriesManager) + ISsdpCommunicationsServer communicationsServer, + INetworkManager networkManager) { _config = config; _appHost = appHost; @@ -93,37 +88,10 @@ namespace Emby.Dlna.Main _mediaSourceManager = mediaSourceManager; _deviceDiscovery = deviceDiscovery; _mediaEncoder = mediaEncoder; - _socketFactory = socketFactory; + _communicationsServer = communicationsServer; _networkManager = networkManager; _logger = loggerFactory.CreateLogger<DlnaEntryPoint>(); - ContentDirectory = new ContentDirectory.ContentDirectoryService( - dlnaManager, - userDataManager, - imageProcessor, - libraryManager, - config, - userManager, - loggerFactory.CreateLogger<ContentDirectory.ContentDirectoryService>(), - httpClientFactory, - localizationManager, - mediaSourceManager, - userViewManager, - mediaEncoder, - tvSeriesManager); - - ConnectionManager = new ConnectionManager.ConnectionManagerService( - dlnaManager, - config, - loggerFactory.CreateLogger<ConnectionManager.ConnectionManagerService>(), - httpClientFactory); - - MediaReceiverRegistrar = new MediaReceiverRegistrar.MediaReceiverRegistrarService( - loggerFactory.CreateLogger<MediaReceiverRegistrar.MediaReceiverRegistrarService>(), - httpClientFactory, - config); - Current = this; - var netConfig = config.GetConfiguration<NetworkConfiguration>(NetworkConfigurationStore.StoreKey); _disabled = appHost.ListenWithHttps && netConfig.RequireHttps; @@ -133,19 +101,6 @@ namespace Emby.Dlna.Main } } - public static DlnaEntryPoint Current { get; private set; } - - /// <summary> - /// Gets a value indicating whether the dlna server is enabled. - /// </summary> - public static bool Enabled { get; private set; } - - public IContentDirectory ContentDirectory { get; private set; } - - public IConnectionManager ConnectionManager { get; private set; } - - public IMediaReceiverRegistrar MediaReceiverRegistrar { get; private set; } - public async Task RunAsync() { await ((DlnaManager)_dlnaManager).InitProfilesAsync().ConfigureAwait(false); @@ -172,9 +127,7 @@ namespace Emby.Dlna.Main private void ReloadComponents() { var options = _config.GetDlnaConfiguration(); - Enabled = options.EnableServer; - - StartSsdpHandler(); + StartDeviceDiscovery(); if (options.EnableServer) { @@ -195,36 +148,11 @@ namespace Emby.Dlna.Main } } - private void StartSsdpHandler() - { - try - { - if (_communicationsServer is null) - { - var enableMultiSocketBinding = OperatingSystem.IsWindows() || OperatingSystem.IsLinux(); - - _communicationsServer = new SsdpCommunicationsServer(_socketFactory, _networkManager, _logger, enableMultiSocketBinding) - { - IsShared = true - }; - - StartDeviceDiscovery(_communicationsServer); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error starting ssdp handlers"); - } - } - - private void StartDeviceDiscovery(ISsdpCommunicationsServer communicationsServer) + private void StartDeviceDiscovery() { try { - if (communicationsServer is not null) - { - ((DeviceDiscovery)_deviceDiscovery).Start(communicationsServer); - } + ((DeviceDiscovery)_deviceDiscovery).Start(_communicationsServer); } catch (Exception ex) { @@ -232,19 +160,6 @@ namespace Emby.Dlna.Main } } - private void DisposeDeviceDiscovery() - { - try - { - _logger.LogInformation("Disposing DeviceDiscovery"); - ((DeviceDiscovery)_deviceDiscovery).Dispose(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error stopping device discovery"); - } - } - public void StartDevicePublisher(Configuration.DlnaOptions options) { if (_publisher is not null) @@ -317,7 +232,7 @@ namespace Emby.Dlna.Main // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc. }; - SetProperies(device, fullService); + SetProperties(device, fullService); _publisher.AddDevice(device); var embeddedDevices = new[] @@ -338,13 +253,13 @@ namespace Emby.Dlna.Main // This must be a globally unique value that survives reboots etc. Get from storage or embedded hardware etc. }; - SetProperies(embeddedDevice, subDevice); + SetProperties(embeddedDevice, subDevice); device.AddDevice(embeddedDevice); } } } - private string CreateUuid(string text) + private static string CreateUuid(string text) { if (!Guid.TryParse(text, out var guid)) { @@ -354,15 +269,14 @@ namespace Emby.Dlna.Main return guid.ToString("D", CultureInfo.InvariantCulture); } - private void SetProperies(SsdpDevice device, string fullDeviceType) + private static void SetProperties(SsdpDevice device, string fullDeviceType) { - var service = fullDeviceType.Replace("urn:", string.Empty, StringComparison.OrdinalIgnoreCase).Replace(":1", string.Empty, StringComparison.OrdinalIgnoreCase); - - var serviceParts = service.Split(':'); - - var deviceTypeNamespace = serviceParts[0].Replace('.', '-'); + var serviceParts = fullDeviceType + .Replace("urn:", string.Empty, StringComparison.OrdinalIgnoreCase) + .Replace(":1", string.Empty, StringComparison.OrdinalIgnoreCase) + .Split(':'); - device.DeviceTypeNamespace = deviceTypeNamespace; + device.DeviceTypeNamespace = serviceParts[0].Replace('.', '-'); device.DeviceClass = serviceParts[1]; device.DeviceType = serviceParts[2]; } @@ -443,20 +357,6 @@ namespace Emby.Dlna.Main DisposeDevicePublisher(); DisposePlayToManager(); - DisposeDeviceDiscovery(); - - if (_communicationsServer is not null) - { - _logger.LogInformation("Disposing SsdpCommunicationsServer"); - _communicationsServer.Dispose(); - _communicationsServer = null; - } - - ContentDirectory = null; - ConnectionManager = null; - MediaReceiverRegistrar = null; - Current = null; - _disposed = true; } } diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index d21cc69132..18fa196508 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -927,14 +927,11 @@ namespace Emby.Dlna.PlayTo var resElement = container.Element(UPnpNamespaces.Res); - if (resElement is not null) - { - var info = resElement.Attribute(UPnpNamespaces.ProtocolInfo); + var info = resElement?.Attribute(UPnpNamespaces.ProtocolInfo); - if (info is not null && !string.IsNullOrWhiteSpace(info.Value)) - { - return info.Value.Split(':'); - } + if (info is not null && !string.IsNullOrWhiteSpace(info.Value)) + { + return info.Value.Split(':'); } return new string[4]; @@ -1139,7 +1136,6 @@ namespace Emby.Dlna.PlayTo return new Device(deviceProperties, httpClientFactory, logger); } -#nullable enable private static DeviceIcon CreateIcon(XElement element) { ArgumentNullException.ThrowIfNull(element); @@ -1252,11 +1248,10 @@ namespace Emby.Dlna.PlayTo if (disposing) { _timer?.Dispose(); + _timer = null; + Properties = null!; } - _timer = null; - Properties = null!; - _disposed = true; } diff --git a/Emby.Dlna/PlayTo/DlnaHttpClient.cs b/Emby.Dlna/PlayTo/DlnaHttpClient.cs index 220aa1a8dc..255c51f19a 100644 --- a/Emby.Dlna/PlayTo/DlnaHttpClient.cs +++ b/Emby.Dlna/PlayTo/DlnaHttpClient.cs @@ -55,41 +55,42 @@ namespace Emby.Dlna.PlayTo var client = _httpClientFactory.CreateClient(NamedClient.Dlna); using var response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false); response.EnsureSuccessStatusCode(); - await using MemoryStream ms = new MemoryStream(); - await response.Content.CopyToAsync(ms, cancellationToken).ConfigureAwait(false); - ms.Position = 0; - try + Stream stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + await using (stream.ConfigureAwait(false)) { - return await XDocument.LoadAsync( - ms, - LoadOptions.None, - cancellationToken).ConfigureAwait(false); - } - catch (XmlException) - { - // try correcting the Xml response with common errors - ms.Position = 0; - using StreamReader sr = new StreamReader(ms); - var xmlString = await sr.ReadToEndAsync(cancellationToken).ConfigureAwait(false); - - // find and replace unescaped ampersands (&) - xmlString = EscapeAmpersandRegex().Replace(xmlString, "&"); - try { - // retry reading Xml - using var xmlReader = new StringReader(xmlString); return await XDocument.LoadAsync( - xmlReader, + stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); } - catch (XmlException ex) + catch (XmlException) { - _logger.LogError(ex, "Failed to parse response"); - _logger.LogDebug("Malformed response: {Content}\n", xmlString); - - return null; + // try correcting the Xml response with common errors + stream.Position = 0; + using StreamReader sr = new StreamReader(stream); + var xmlString = await sr.ReadToEndAsync(cancellationToken).ConfigureAwait(false); + + // find and replace unescaped ampersands (&) + xmlString = EscapeAmpersandRegex().Replace(xmlString, "&"); + + try + { + // retry reading Xml + using var xmlReader = new StringReader(xmlString); + return await XDocument.LoadAsync( + xmlReader, + LoadOptions.None, + cancellationToken).ConfigureAwait(false); + } + catch (XmlException ex) + { + _logger.LogError(ex, "Failed to parse response"); + _logger.LogDebug("Malformed response: {Content}\n", xmlString); + + return null; + } } } } diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 9e3d1d4d6d..f70ebf3ebc 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -684,16 +684,15 @@ namespace Emby.Dlna.PlayTo if (disposing) { + _device.PlaybackStart -= OnDevicePlaybackStart; + _device.PlaybackProgress -= OnDevicePlaybackProgress; + _device.PlaybackStopped -= OnDevicePlaybackStopped; + _device.MediaChanged -= OnDeviceMediaChanged; + _deviceDiscovery.DeviceLeft -= OnDeviceDiscoveryDeviceLeft; + _device.OnDeviceUnavailable = null; _device.Dispose(); } - _device.PlaybackStart -= OnDevicePlaybackStart; - _device.PlaybackProgress -= OnDevicePlaybackProgress; - _device.PlaybackStopped -= OnDevicePlaybackStopped; - _device.MediaChanged -= OnDeviceMediaChanged; - _deviceDiscovery.DeviceLeft -= OnDeviceDiscoveryDeviceLeft; - _device.OnDeviceUnavailable = null; - _disposed = true; } diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index ef617422c4..b05e0a0957 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -39,9 +39,9 @@ namespace Emby.Dlna.PlayTo private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaEncoder _mediaEncoder; + private readonly SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1); + private readonly CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource(); 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, IHttpClientFactory httpClientFactory, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder) { |
