aboutsummaryrefslogtreecommitdiff
path: root/Emby.Dlna/PlayTo/Device.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Dlna/PlayTo/Device.cs')
-rw-r--r--Emby.Dlna/PlayTo/Device.cs401
1 files changed, 168 insertions, 233 deletions
diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs
index 6c580d15bd..d21cc69132 100644
--- a/Emby.Dlna/PlayTo/Device.cs
+++ b/Emby.Dlna/PlayTo/Device.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
#pragma warning disable CS1591
using System;
@@ -20,14 +18,12 @@ namespace Emby.Dlna.PlayTo
{
public class Device : IDisposable
{
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger _logger;
private readonly object _timerLock = new object();
- private Timer _timer;
+ private Timer? _timer;
private int _muteVol;
private int _volume;
private DateTime _lastVolumeRefresh;
@@ -42,13 +38,13 @@ namespace Emby.Dlna.PlayTo
_logger = logger;
}
- public event EventHandler<PlaybackStartEventArgs> PlaybackStart;
+ public event EventHandler<PlaybackStartEventArgs>? PlaybackStart;
- public event EventHandler<PlaybackProgressEventArgs> PlaybackProgress;
+ public event EventHandler<PlaybackProgressEventArgs>? PlaybackProgress;
- public event EventHandler<PlaybackStoppedEventArgs> PlaybackStopped;
+ public event EventHandler<PlaybackStoppedEventArgs>? PlaybackStopped;
- public event EventHandler<MediaChangedEventArgs> MediaChanged;
+ public event EventHandler<MediaChangedEventArgs>? MediaChanged;
public DeviceInfo Properties { get; set; }
@@ -71,19 +67,19 @@ namespace Emby.Dlna.PlayTo
public TransportState TransportState { get; private set; }
- public bool IsPlaying => TransportState == TransportState.Playing;
+ public bool IsPlaying => TransportState == TransportState.PLAYING;
- public bool IsPaused => TransportState == TransportState.Paused || TransportState == TransportState.PausedPlayback;
+ public bool IsPaused => TransportState == TransportState.PAUSED_PLAYBACK;
- public bool IsStopped => TransportState == TransportState.Stopped;
+ public bool IsStopped => TransportState == TransportState.STOPPED;
- public Action OnDeviceUnavailable { get; set; }
+ public Action? OnDeviceUnavailable { get; set; }
- private TransportCommands AvCommands { get; set; }
+ private TransportCommands? AvCommands { get; set; }
- private TransportCommands RendererCommands { get; set; }
+ private TransportCommands? RendererCommands { get; set; }
- public UBaseObject CurrentMediaInfo { get; private set; }
+ public UBaseObject? CurrentMediaInfo { get; private set; }
public void Start()
{
@@ -133,7 +129,7 @@ namespace Emby.Dlna.PlayTo
_volumeRefreshActive = true;
var time = immediate ? 100 : 10000;
- _timer.Change(time, Timeout.Infinite);
+ _timer?.Change(time, Timeout.Infinite);
}
}
@@ -151,7 +147,7 @@ namespace Emby.Dlna.PlayTo
_volumeRefreshActive = false;
- _timer.Change(Timeout.Infinite, Timeout.Infinite);
+ _timer?.Change(Timeout.Infinite, Timeout.Infinite);
}
}
@@ -201,7 +197,7 @@ namespace Emby.Dlna.PlayTo
}
}
- private DeviceService GetServiceRenderingControl()
+ private DeviceService? GetServiceRenderingControl()
{
var services = Properties.Services;
@@ -209,7 +205,7 @@ namespace Emby.Dlna.PlayTo
services.FirstOrDefault(s => (s.ServiceType ?? string.Empty).StartsWith("urn:schemas-upnp-org:service:RenderingControl", StringComparison.OrdinalIgnoreCase));
}
- private DeviceService GetAvTransportService()
+ private DeviceService? GetAvTransportService()
{
var services = Properties.Services;
@@ -222,14 +218,14 @@ namespace Emby.Dlna.PlayTo
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
var command = rendererCommands?.ServiceActions.FirstOrDefault(c => c.Name == "SetMute");
- if (command == null)
+ if (command is null)
{
return false;
}
var service = GetServiceRenderingControl();
- if (service == null)
+ if (service is null)
{
return false;
}
@@ -237,12 +233,12 @@ namespace Emby.Dlna.PlayTo
_logger.LogDebug("Setting mute");
var value = mute ? 1 : 0;
- await new SsdpHttpClient(_httpClientFactory)
+ await new DlnaHttpClient(_logger, _httpClientFactory)
.SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
- rendererCommands.BuildPost(command, service.ServiceType, value),
+ rendererCommands!.BuildPost(command, service.ServiceType, value), // null checked above
cancellationToken: cancellationToken)
.ConfigureAwait(false);
@@ -262,28 +258,23 @@ namespace Emby.Dlna.PlayTo
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
var command = rendererCommands?.ServiceActions.FirstOrDefault(c => c.Name == "SetVolume");
- if (command == null)
+ if (command is null)
{
return;
}
- var service = GetServiceRenderingControl();
-
- if (service == null)
- {
- throw new InvalidOperationException("Unable to find service");
- }
+ var service = GetServiceRenderingControl() ?? throw new InvalidOperationException("Unable to find service");
// Set it early and assume it will succeed
// Remote control will perform better
Volume = value;
- await new SsdpHttpClient(_httpClientFactory)
+ await new DlnaHttpClient(_logger, _httpClientFactory)
.SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
- rendererCommands.BuildPost(command, service.ServiceType, value),
+ rendererCommands!.BuildPost(command, service.ServiceType, value), // null checked above
cancellationToken: cancellationToken)
.ConfigureAwait(false);
}
@@ -293,31 +284,25 @@ namespace Emby.Dlna.PlayTo
var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
var command = avCommands?.ServiceActions.FirstOrDefault(c => c.Name == "Seek");
- if (command == null)
+ if (command is null)
{
return;
}
- var service = GetAvTransportService();
-
- if (service == null)
- {
- throw new InvalidOperationException("Unable to find service");
- }
-
- await new SsdpHttpClient(_httpClientFactory)
+ var service = GetAvTransportService() ?? throw new InvalidOperationException("Unable to find service");
+ await new DlnaHttpClient(_logger, _httpClientFactory)
.SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
- avCommands.BuildPost(command, service.ServiceType, string.Format(CultureInfo.InvariantCulture, "{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME"),
+ avCommands!.BuildPost(command, service.ServiceType, string.Format(CultureInfo.InvariantCulture, "{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME"), // null checked above
cancellationToken: cancellationToken)
.ConfigureAwait(false);
RestartTimer(true);
}
- public async Task SetAvTransport(string url, string header, string metaData, CancellationToken cancellationToken)
+ public async Task SetAvTransport(string url, string? header, string metaData, CancellationToken cancellationToken)
{
var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
@@ -326,7 +311,7 @@ namespace Emby.Dlna.PlayTo
_logger.LogDebug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", Properties.Name, url, header);
var command = avCommands?.ServiceActions.FirstOrDefault(c => c.Name == "SetAVTransportURI");
- if (command == null)
+ if (command is null)
{
return;
}
@@ -337,15 +322,9 @@ namespace Emby.Dlna.PlayTo
{ "CurrentURIMetaData", CreateDidlMeta(metaData) }
};
- var service = GetAvTransportService();
-
- if (service == null)
- {
- throw new InvalidOperationException("Unable to find service");
- }
-
- var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
- await new SsdpHttpClient(_httpClientFactory)
+ var service = GetAvTransportService() ?? throw new InvalidOperationException("Unable to find service");
+ var post = avCommands!.BuildPost(command, service.ServiceType, url, dictionary); // null checked above
+ await new DlnaHttpClient(_logger, _httpClientFactory)
.SendCommandAsync(
Properties.BaseUrl,
service,
@@ -374,7 +353,7 @@ namespace Emby.Dlna.PlayTo
* SetNextAvTransport is used to specify to the DLNA device what is the next track to play.
* Without that information, the next track command on the device does not work.
*/
- public async Task SetNextAvTransport(string url, string header, string metaData, CancellationToken cancellationToken = default)
+ public async Task SetNextAvTransport(string url, string? header, string metaData, CancellationToken cancellationToken = default)
{
var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
@@ -382,8 +361,8 @@ namespace Emby.Dlna.PlayTo
_logger.LogDebug("{PropertyName} - SetNextAvTransport Uri: {Url} DlnaHeaders: {Header}", Properties.Name, url, header);
- var command = avCommands.ServiceActions.FirstOrDefault(c => string.Equals(c.Name, "SetNextAVTransportURI", StringComparison.OrdinalIgnoreCase));
- if (command == null)
+ var command = avCommands?.ServiceActions.FirstOrDefault(c => string.Equals(c.Name, "SetNextAVTransportURI", StringComparison.OrdinalIgnoreCase));
+ if (command is null)
{
return;
}
@@ -394,15 +373,10 @@ namespace Emby.Dlna.PlayTo
{ "NextURIMetaData", CreateDidlMeta(metaData) }
};
- var service = GetAvTransportService();
-
- if (service == null)
- {
- throw new InvalidOperationException("Unable to find service");
- }
-
- var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
- await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header, cancellationToken)
+ var service = GetAvTransportService() ?? throw new InvalidOperationException("Unable to find service");
+ var post = avCommands!.BuildPost(command, service.ServiceType, url, dictionary); // null checked above
+ await new DlnaHttpClient(_logger, _httpClientFactory)
+ .SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header, cancellationToken)
.ConfigureAwait(false);
}
@@ -419,18 +393,13 @@ namespace Emby.Dlna.PlayTo
private Task SetPlay(TransportCommands avCommands, CancellationToken cancellationToken)
{
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "Play");
- if (command == null)
+ if (command is null)
{
return Task.CompletedTask;
}
- var service = GetAvTransportService();
- if (service == null)
- {
- throw new InvalidOperationException("Unable to find service");
- }
-
- return new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+ var service = GetAvTransportService() ?? throw new InvalidOperationException("Unable to find service");
+ return new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
@@ -441,7 +410,7 @@ namespace Emby.Dlna.PlayTo
public async Task SetPlay(CancellationToken cancellationToken)
{
var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
- if (avCommands == null)
+ if (avCommands is null)
{
return;
}
@@ -456,19 +425,18 @@ namespace Emby.Dlna.PlayTo
var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
var command = avCommands?.ServiceActions.FirstOrDefault(c => c.Name == "Stop");
- if (command == null)
+ if (command is null)
{
return;
}
- var service = GetAvTransportService();
-
- await new SsdpHttpClient(_httpClientFactory)
+ var service = GetAvTransportService() ?? throw new InvalidOperationException("Unable to find service");
+ await new DlnaHttpClient(_logger, _httpClientFactory)
.SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
- avCommands.BuildPost(command, service.ServiceType, 1),
+ avCommands!.BuildPost(command, service.ServiceType, 1), // null checked above
cancellationToken: cancellationToken)
.ConfigureAwait(false);
@@ -480,28 +448,27 @@ namespace Emby.Dlna.PlayTo
var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
var command = avCommands?.ServiceActions.FirstOrDefault(c => c.Name == "Pause");
- if (command == null)
+ if (command is null)
{
return;
}
- var service = GetAvTransportService();
-
- await new SsdpHttpClient(_httpClientFactory)
+ var service = GetAvTransportService() ?? throw new InvalidOperationException("Unable to find service");
+ await new DlnaHttpClient(_logger, _httpClientFactory)
.SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
- avCommands.BuildPost(command, service.ServiceType, 1),
+ avCommands!.BuildPost(command, service.ServiceType, 1), // null checked above
cancellationToken: cancellationToken)
.ConfigureAwait(false);
- TransportState = TransportState.Paused;
+ TransportState = TransportState.PAUSED_PLAYBACK;
RestartTimer(true);
}
- private async void TimerCallback(object sender)
+ private async void TimerCallback(object? sender)
{
if (_disposed)
{
@@ -514,7 +481,7 @@ namespace Emby.Dlna.PlayTo
var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
- if (avCommands == null)
+ if (avCommands is null)
{
return;
}
@@ -529,7 +496,7 @@ namespace Emby.Dlna.PlayTo
if (transportState.HasValue)
{
// If we're not playing anything no need to get additional data
- if (transportState.Value == TransportState.Stopped)
+ if (transportState.Value == TransportState.STOPPED)
{
UpdateMediaInfo(null, transportState.Value);
}
@@ -537,14 +504,14 @@ namespace Emby.Dlna.PlayTo
{
var tuple = await GetPositionInfo(avCommands, cancellationToken).ConfigureAwait(false);
- var currentObject = tuple.Item2;
+ var currentObject = tuple.Track;
- if (tuple.Item1 && currentObject == null)
+ if (tuple.Success && currentObject is null)
{
currentObject = await GetMediaInfo(avCommands, cancellationToken).ConfigureAwait(false);
}
- if (currentObject != null)
+ if (currentObject is not null)
{
UpdateMediaInfo(currentObject, transportState.Value);
}
@@ -558,7 +525,7 @@ namespace Emby.Dlna.PlayTo
}
// If we're not playing anything make sure we don't get data more often than necessary to keep the Session alive
- if (transportState.Value == TransportState.Stopped)
+ if (transportState.Value == TransportState.STOPPED)
{
RestartTimerInactive();
}
@@ -586,7 +553,7 @@ namespace Emby.Dlna.PlayTo
if (_connectFailureCount >= 3)
{
var action = OnDeviceUnavailable;
- if (action != null)
+ if (action is not null)
{
_logger.LogDebug("Disposing device due to loss of connection");
action();
@@ -608,31 +575,31 @@ namespace Emby.Dlna.PlayTo
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
var command = rendererCommands?.ServiceActions.FirstOrDefault(c => c.Name == "GetVolume");
- if (command == null)
+ if (command is null)
{
return;
}
var service = GetServiceRenderingControl();
- if (service == null)
+ if (service is null)
{
return;
}
- var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+ var result = await new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
- rendererCommands.BuildPost(command, service.ServiceType),
+ rendererCommands!.BuildPost(command, service.ServiceType), // null checked above
cancellationToken: cancellationToken).ConfigureAwait(false);
- if (result == null || result.Document == null)
+ if (result is null || result.Document is null)
{
return;
}
- var volume = result.Document.Descendants(UPnpNamespaces.RenderingControl + "GetVolumeResponse").Select(i => i.Element("CurrentVolume")).FirstOrDefault(i => i != null);
+ var volume = result.Document.Descendants(UPnpNamespaces.RenderingControl + "GetVolumeResponse").Select(i => i.Element("CurrentVolume")).FirstOrDefault(i => i is not null);
var volumeValue = volume?.Value;
if (string.IsNullOrWhiteSpace(volumeValue))
@@ -640,7 +607,7 @@ namespace Emby.Dlna.PlayTo
return;
}
- Volume = int.Parse(volumeValue, UsCulture);
+ Volume = int.Parse(volumeValue, CultureInfo.InvariantCulture);
if (Volume > 0)
{
@@ -658,33 +625,33 @@ namespace Emby.Dlna.PlayTo
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
var command = rendererCommands?.ServiceActions.FirstOrDefault(c => c.Name == "GetMute");
- if (command == null)
+ if (command is null)
{
return;
}
var service = GetServiceRenderingControl();
- if (service == null)
+ if (service is null)
{
return;
}
- var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+ var result = await new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
- rendererCommands.BuildPost(command, service.ServiceType),
+ rendererCommands!.BuildPost(command, service.ServiceType), // null checked above
cancellationToken: cancellationToken).ConfigureAwait(false);
- if (result == null || result.Document == null)
+ if (result is null || result.Document is null)
{
return;
}
var valueNode = result.Document.Descendants(UPnpNamespaces.RenderingControl + "GetMuteResponse")
.Select(i => i.Element("CurrentMute"))
- .FirstOrDefault(i => i != null);
+ .FirstOrDefault(i => i is not null);
IsMuted = string.Equals(valueNode?.Value, "1", StringComparison.OrdinalIgnoreCase);
}
@@ -692,35 +659,35 @@ namespace Emby.Dlna.PlayTo
private async Task<TransportState?> GetTransportInfo(TransportCommands avCommands, CancellationToken cancellationToken)
{
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetTransportInfo");
- if (command == null)
+ if (command is null)
{
return null;
}
var service = GetAvTransportService();
- if (service == null)
+ if (service is null)
{
return null;
}
- var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+ var result = await new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
avCommands.BuildPost(command, service.ServiceType),
cancellationToken: cancellationToken).ConfigureAwait(false);
- if (result == null || result.Document == null)
+ if (result is null || result.Document is null)
{
return null;
}
var transportState =
- result.Document.Descendants(UPnpNamespaces.AvTransport + "GetTransportInfoResponse").Select(i => i.Element("CurrentTransportState")).FirstOrDefault(i => i != null);
+ result.Document.Descendants(UPnpNamespaces.AvTransport + "GetTransportInfoResponse").Select(i => i.Element("CurrentTransportState")).FirstOrDefault(i => i is not null);
var transportStateValue = transportState?.Value;
- if (transportStateValue != null
+ if (transportStateValue is not null
&& Enum.TryParse(transportStateValue, true, out TransportState state))
{
return state;
@@ -729,41 +696,41 @@ namespace Emby.Dlna.PlayTo
return null;
}
- private async Task<UBaseObject> GetMediaInfo(TransportCommands avCommands, CancellationToken cancellationToken)
+ private async Task<UBaseObject?> GetMediaInfo(TransportCommands avCommands, CancellationToken cancellationToken)
{
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMediaInfo");
- if (command == null)
+ if (command is null)
{
return null;
}
var service = GetAvTransportService();
- if (service == null)
+ if (service is null)
{
throw new InvalidOperationException("Unable to find service");
}
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
- if (rendererCommands == null)
+ if (rendererCommands is null)
{
return null;
}
- var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+ var result = await new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
rendererCommands.BuildPost(command, service.ServiceType),
cancellationToken: cancellationToken).ConfigureAwait(false);
- if (result == null || result.Document == null)
+ if (result is null || result.Document is null)
{
return null;
}
var track = result.Document.Descendants("CurrentURIMetaData").FirstOrDefault();
- if (track == null)
+ if (track is null)
{
return null;
}
@@ -779,7 +746,7 @@ namespace Emby.Dlna.PlayTo
track = result.Document.Descendants("CurrentURI").FirstOrDefault();
- if (track == null)
+ if (track is null)
{
return null;
}
@@ -799,67 +766,67 @@ namespace Emby.Dlna.PlayTo
return null;
}
- private async Task<(bool, UBaseObject)> GetPositionInfo(TransportCommands avCommands, CancellationToken cancellationToken)
+ private async Task<(bool Success, UBaseObject? Track)> GetPositionInfo(TransportCommands avCommands, CancellationToken cancellationToken)
{
var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetPositionInfo");
- if (command == null)
+ if (command is null)
{
return (false, null);
}
var service = GetAvTransportService();
- if (service == null)
+ if (service is null)
{
throw new InvalidOperationException("Unable to find service");
}
var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
- if (rendererCommands == null)
+ if (rendererCommands is null)
{
return (false, null);
}
- var result = await new SsdpHttpClient(_httpClientFactory).SendCommandAsync(
+ var result = await new DlnaHttpClient(_logger, _httpClientFactory).SendCommandAsync(
Properties.BaseUrl,
service,
command.Name,
rendererCommands.BuildPost(command, service.ServiceType),
cancellationToken: cancellationToken).ConfigureAwait(false);
- if (result == null || result.Document == null)
+ if (result is null || result.Document is null)
{
return (false, null);
}
- var trackUriElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackURI")).FirstOrDefault(i => i != null);
+ var trackUriElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackURI")).FirstOrDefault(i => i is not null);
var trackUri = trackUriElem?.Value;
- var durationElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackDuration")).FirstOrDefault(i => i != null);
+ var durationElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("TrackDuration")).FirstOrDefault(i => i is not null);
var duration = durationElem?.Value;
if (!string.IsNullOrWhiteSpace(duration)
&& !string.Equals(duration, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
{
- Duration = TimeSpan.Parse(duration, UsCulture);
+ Duration = TimeSpan.Parse(duration, CultureInfo.InvariantCulture);
}
else
{
Duration = null;
}
- var positionElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("RelTime")).FirstOrDefault(i => i != null);
+ var positionElem = result.Document.Descendants(UPnpNamespaces.AvTransport + "GetPositionInfoResponse").Select(i => i.Element("RelTime")).FirstOrDefault(i => i is not null);
var position = positionElem?.Value;
if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase))
{
- Position = TimeSpan.Parse(position, UsCulture);
+ Position = TimeSpan.Parse(position, CultureInfo.InvariantCulture);
}
var track = result.Document.Descendants("TrackMetaData").FirstOrDefault();
- if (track == null)
+ if (track is null)
{
// If track is null, some vendors do this, use GetMediaInfo instead.
return (true, null);
@@ -872,7 +839,7 @@ namespace Emby.Dlna.PlayTo
return (true, null);
}
- XElement uPnpResponse = null;
+ XElement? uPnpResponse = null;
try
{
@@ -883,7 +850,7 @@ namespace Emby.Dlna.PlayTo
_logger.LogError(ex, "Uncaught exception while parsing xml");
}
- if (uPnpResponse == null)
+ if (uPnpResponse is null)
{
_logger.LogError("Failed to parse xml: \n {Xml}", trackString);
return (true, null);
@@ -896,7 +863,7 @@ namespace Emby.Dlna.PlayTo
return (true, uTrack);
}
- private XElement ParseResponse(string xml)
+ private XElement? ParseResponse(string xml)
{
// Handle different variations sent back by devices.
try
@@ -930,12 +897,9 @@ namespace Emby.Dlna.PlayTo
return null;
}
- private static UBaseObject CreateUBaseObject(XElement container, string trackUri)
+ private static UBaseObject CreateUBaseObject(XElement? container, string? trackUri)
{
- if (container == null)
- {
- throw new ArgumentNullException(nameof(container));
- }
+ ArgumentNullException.ThrowIfNull(container);
var url = container.GetValue(UPnpNamespaces.Res);
@@ -959,18 +923,15 @@ namespace Emby.Dlna.PlayTo
private static string[] GetProtocolInfo(XElement container)
{
- if (container == null)
- {
- throw new ArgumentNullException(nameof(container));
- }
+ ArgumentNullException.ThrowIfNull(container);
var resElement = container.Element(UPnpNamespaces.Res);
- if (resElement != null)
+ if (resElement is not null)
{
var info = resElement.Attribute(UPnpNamespaces.ProtocolInfo);
- if (info != null && !string.IsNullOrWhiteSpace(info.Value))
+ if (info is not null && !string.IsNullOrWhiteSpace(info.Value))
{
return info.Value.Split(':');
}
@@ -979,9 +940,9 @@ namespace Emby.Dlna.PlayTo
return new string[4];
}
- private async Task<TransportCommands> GetAVProtocolAsync(CancellationToken cancellationToken)
+ private async Task<TransportCommands?> GetAVProtocolAsync(CancellationToken cancellationToken)
{
- if (AvCommands != null)
+ if (AvCommands is not null)
{
return AvCommands;
}
@@ -992,17 +953,17 @@ namespace Emby.Dlna.PlayTo
}
var avService = GetAvTransportService();
- if (avService == null)
+ if (avService is null)
{
return null;
}
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
- var httpClient = new SsdpHttpClient(_httpClientFactory);
+ var httpClient = new DlnaHttpClient(_logger, _httpClientFactory);
var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
- if (document == null)
+ if (document is null)
{
return null;
}
@@ -1011,9 +972,9 @@ namespace Emby.Dlna.PlayTo
return AvCommands;
}
- private async Task<TransportCommands> GetRenderingProtocolAsync(CancellationToken cancellationToken)
+ private async Task<TransportCommands?> GetRenderingProtocolAsync(CancellationToken cancellationToken)
{
- if (RendererCommands != null)
+ if (RendererCommands is not null)
{
return RendererCommands;
}
@@ -1024,17 +985,14 @@ namespace Emby.Dlna.PlayTo
}
var avService = GetServiceRenderingControl();
- if (avService == null)
- {
- throw new ArgumentException("Device AvService is null");
- }
+ ArgumentNullException.ThrowIfNull(avService);
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
- var httpClient = new SsdpHttpClient(_httpClientFactory);
+ var httpClient = new DlnaHttpClient(_logger, _httpClientFactory);
_logger.LogDebug("Dlna Device.GetRenderingProtocolAsync");
var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
- if (document == null)
+ if (document is null)
{
return null;
}
@@ -1064,12 +1022,12 @@ namespace Emby.Dlna.PlayTo
return baseUrl + url;
}
- public static async Task<Device> CreateuPnpDeviceAsync(Uri url, IHttpClientFactory httpClientFactory, ILogger logger, CancellationToken cancellationToken)
+ public static async Task<Device?> CreateuPnpDeviceAsync(Uri url, IHttpClientFactory httpClientFactory, ILogger logger, CancellationToken cancellationToken)
{
- var ssdpHttpClient = new SsdpHttpClient(httpClientFactory);
+ var ssdpHttpClient = new DlnaHttpClient(logger, httpClientFactory);
var document = await ssdpHttpClient.GetDataAsync(url.ToString(), cancellationToken).ConfigureAwait(false);
- if (document == null)
+ if (document is null)
{
return null;
}
@@ -1077,13 +1035,13 @@ namespace Emby.Dlna.PlayTo
var friendlyNames = new List<string>();
var name = document.Descendants(UPnpNamespaces.Ud.GetName("friendlyName")).FirstOrDefault();
- if (name != null && !string.IsNullOrWhiteSpace(name.Value))
+ if (name is not null && !string.IsNullOrWhiteSpace(name.Value))
{
friendlyNames.Add(name.Value);
}
var room = document.Descendants(UPnpNamespaces.Ud.GetName("roomName")).FirstOrDefault();
- if (room != null && !string.IsNullOrWhiteSpace(room.Value))
+ if (room is not null && !string.IsNullOrWhiteSpace(room.Value))
{
friendlyNames.Add(room.Value);
}
@@ -1095,74 +1053,74 @@ namespace Emby.Dlna.PlayTo
};
var model = document.Descendants(UPnpNamespaces.Ud.GetName("modelName")).FirstOrDefault();
- if (model != null)
+ if (model is not null)
{
deviceProperties.ModelName = model.Value;
}
var modelNumber = document.Descendants(UPnpNamespaces.Ud.GetName("modelNumber")).FirstOrDefault();
- if (modelNumber != null)
+ if (modelNumber is not null)
{
deviceProperties.ModelNumber = modelNumber.Value;
}
var uuid = document.Descendants(UPnpNamespaces.Ud.GetName("UDN")).FirstOrDefault();
- if (uuid != null)
+ if (uuid is not null)
{
deviceProperties.UUID = uuid.Value;
}
var manufacturer = document.Descendants(UPnpNamespaces.Ud.GetName("manufacturer")).FirstOrDefault();
- if (manufacturer != null)
+ if (manufacturer is not null)
{
deviceProperties.Manufacturer = manufacturer.Value;
}
var manufacturerUrl = document.Descendants(UPnpNamespaces.Ud.GetName("manufacturerURL")).FirstOrDefault();
- if (manufacturerUrl != null)
+ if (manufacturerUrl is not null)
{
deviceProperties.ManufacturerUrl = manufacturerUrl.Value;
}
var presentationUrl = document.Descendants(UPnpNamespaces.Ud.GetName("presentationURL")).FirstOrDefault();
- if (presentationUrl != null)
+ if (presentationUrl is not null)
{
deviceProperties.PresentationUrl = presentationUrl.Value;
}
var modelUrl = document.Descendants(UPnpNamespaces.Ud.GetName("modelURL")).FirstOrDefault();
- if (modelUrl != null)
+ if (modelUrl is not null)
{
deviceProperties.ModelUrl = modelUrl.Value;
}
var serialNumber = document.Descendants(UPnpNamespaces.Ud.GetName("serialNumber")).FirstOrDefault();
- if (serialNumber != null)
+ if (serialNumber is not null)
{
deviceProperties.SerialNumber = serialNumber.Value;
}
var modelDescription = document.Descendants(UPnpNamespaces.Ud.GetName("modelDescription")).FirstOrDefault();
- if (modelDescription != null)
+ if (modelDescription is not null)
{
deviceProperties.ModelDescription = modelDescription.Value;
}
var icon = document.Descendants(UPnpNamespaces.Ud.GetName("icon")).FirstOrDefault();
- if (icon != null)
+ if (icon is not null)
{
deviceProperties.Icon = CreateIcon(icon);
}
foreach (var services in document.Descendants(UPnpNamespaces.Ud.GetName("serviceList")))
{
- if (services == null)
+ if (services is null)
{
continue;
}
var servicesList = services.Descendants(UPnpNamespaces.Ud.GetName("service"));
- if (servicesList == null)
+ if (servicesList is null)
{
continue;
}
@@ -1171,7 +1129,7 @@ namespace Emby.Dlna.PlayTo
{
var service = Create(element);
- if (service != null)
+ if (service is not null)
{
deviceProperties.Services.Add(service);
}
@@ -1181,75 +1139,65 @@ namespace Emby.Dlna.PlayTo
return new Device(deviceProperties, httpClientFactory, logger);
}
+#nullable enable
private static DeviceIcon CreateIcon(XElement element)
{
- if (element == null)
- {
- throw new ArgumentNullException(nameof(element));
- }
+ ArgumentNullException.ThrowIfNull(element);
- var mimeType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("mimetype"));
var width = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("width"));
var height = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("height"));
- var depth = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("depth"));
- var url = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("url"));
- var widthValue = int.Parse(width, NumberStyles.Integer, UsCulture);
- var heightValue = int.Parse(height, NumberStyles.Integer, UsCulture);
+ _ = int.TryParse(width, NumberStyles.Integer, CultureInfo.InvariantCulture, out var widthValue);
+ _ = int.TryParse(height, NumberStyles.Integer, CultureInfo.InvariantCulture, out var heightValue);
return new DeviceIcon
{
- Depth = depth,
+ Depth = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("depth")) ?? string.Empty,
Height = heightValue,
- MimeType = mimeType,
- Url = url,
+ MimeType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("mimetype")) ?? string.Empty,
+ Url = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("url")) ?? string.Empty,
Width = widthValue
};
}
private static DeviceService Create(XElement element)
- {
- var type = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceType"));
- var id = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceId"));
- var scpdUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("SCPDURL"));
- var controlURL = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("controlURL"));
- var eventSubURL = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("eventSubURL"));
-
- return new DeviceService
- {
- ControlUrl = controlURL,
- EventSubUrl = eventSubURL,
- ScpdUrl = scpdUrl,
- ServiceId = id,
- ServiceType = type
+ => new DeviceService()
+ {
+ ControlUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("controlURL")) ?? string.Empty,
+ EventSubUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("eventSubURL")) ?? string.Empty,
+ ScpdUrl = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("SCPDURL")) ?? string.Empty,
+ ServiceId = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceId")) ?? string.Empty,
+ ServiceType = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("serviceType")) ?? string.Empty
};
- }
- private void UpdateMediaInfo(UBaseObject mediaInfo, TransportState state)
+ private void UpdateMediaInfo(UBaseObject? mediaInfo, TransportState state)
{
TransportState = state;
var previousMediaInfo = CurrentMediaInfo;
CurrentMediaInfo = mediaInfo;
- if (previousMediaInfo == null && mediaInfo != null)
+ if (mediaInfo is null)
{
- if (state != TransportState.Stopped)
+ if (previousMediaInfo is not null)
{
- OnPlaybackStart(mediaInfo);
+ OnPlaybackStop(previousMediaInfo);
}
}
- else if (mediaInfo != null && previousMediaInfo != null && !mediaInfo.Equals(previousMediaInfo))
+ else if (previousMediaInfo is null)
{
- OnMediaChanged(previousMediaInfo, mediaInfo);
+ if (state != TransportState.STOPPED)
+ {
+ OnPlaybackStart(mediaInfo);
+ }
}
- else if (mediaInfo == null && previousMediaInfo != null)
+ else if (mediaInfo.Equals(previousMediaInfo))
{
- OnPlaybackStop(previousMediaInfo);
+ OnPlaybackProgress(mediaInfo);
}
- else if (mediaInfo != null && mediaInfo.Equals(previousMediaInfo))
+ else
{
- OnPlaybackProgress(mediaInfo);
+ OnMediaChanged(previousMediaInfo, mediaInfo);
}
}
@@ -1260,10 +1208,7 @@ namespace Emby.Dlna.PlayTo
return;
}
- PlaybackStart?.Invoke(this, new PlaybackStartEventArgs
- {
- MediaInfo = mediaInfo
- });
+ PlaybackStart?.Invoke(this, new PlaybackStartEventArgs(mediaInfo));
}
private void OnPlaybackProgress(UBaseObject mediaInfo)
@@ -1273,27 +1218,17 @@ namespace Emby.Dlna.PlayTo
return;
}
- PlaybackProgress?.Invoke(this, new PlaybackProgressEventArgs
- {
- MediaInfo = mediaInfo
- });
+ PlaybackProgress?.Invoke(this, new PlaybackProgressEventArgs(mediaInfo));
}
private void OnPlaybackStop(UBaseObject mediaInfo)
{
- PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs
- {
- MediaInfo = mediaInfo
- });
+ PlaybackStopped?.Invoke(this, new PlaybackStoppedEventArgs(mediaInfo));
}
private void OnMediaChanged(UBaseObject old, UBaseObject newMedia)
{
- MediaChanged?.Invoke(this, new MediaChangedEventArgs
- {
- OldMediaInfo = old,
- NewMediaInfo = newMedia
- });
+ MediaChanged?.Invoke(this, new MediaChangedEventArgs(old, newMedia));
}
/// <inheritdoc />
@@ -1320,7 +1255,7 @@ namespace Emby.Dlna.PlayTo
}
_timer = null;
- Properties = null;
+ Properties = null!;
_disposed = true;
}