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.cs321
1 files changed, 173 insertions, 148 deletions
diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs
index a617117f3c..9a861b8c7f 100644
--- a/Emby.Dlna/PlayTo/Device.cs
+++ b/Emby.Dlna/PlayTo/Device.cs
@@ -106,27 +106,17 @@ namespace Emby.Dlna.PlayTo
_timerFactory = timerFactory;
}
- private int GetPlaybackTimerIntervalMs()
- {
- return 1000;
- }
-
- private int GetInactiveTimerIntervalMs()
- {
- return 60000;
- }
-
public void Start()
{
- _timer = _timerFactory.Create(TimerCallback, null, GetPlaybackTimerIntervalMs(), GetInactiveTimerIntervalMs());
-
- _timerActive = false;
+ _logger.Debug("Dlna Device.Start");
+ _timer = _timerFactory.Create(TimerCallback, null, 1000, Timeout.Infinite);
}
private DateTime _lastVolumeRefresh;
+ private bool _volumeRefreshActive;
private void RefreshVolumeIfNeeded()
{
- if (!_timerActive)
+ if (!_volumeRefreshActive)
{
return;
}
@@ -134,19 +124,19 @@ namespace Emby.Dlna.PlayTo
if (DateTime.UtcNow >= _lastVolumeRefresh.AddSeconds(5))
{
_lastVolumeRefresh = DateTime.UtcNow;
- RefreshVolume();
+ RefreshVolume(CancellationToken.None);
}
}
- private async void RefreshVolume()
+ private async void RefreshVolume(CancellationToken cancellationToken)
{
if (_disposed)
return;
try
{
- await GetVolume().ConfigureAwait(false);
- await GetMute().ConfigureAwait(false);
+ await GetVolume(cancellationToken).ConfigureAwait(false);
+ await GetMute(cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -155,21 +145,17 @@ namespace Emby.Dlna.PlayTo
}
private readonly object _timerLock = new object();
- private bool _timerActive;
- private void RestartTimer()
+ private void RestartTimer(bool immediate = false)
{
- if (_disposed)
- return;
-
lock (_timerLock)
{
- if (!_timerActive)
- {
- _logger.Debug("RestartTimer");
- _timer.Change(10, GetPlaybackTimerIntervalMs());
- }
+ if (_disposed)
+ return;
+
+ _volumeRefreshActive = true;
- _timerActive = true;
+ var time = immediate ? 100 : 10000;
+ _timer.Change(time, Timeout.Infinite);
}
}
@@ -178,71 +164,67 @@ namespace Emby.Dlna.PlayTo
/// </summary>
private void RestartTimerInactive()
{
- if (_disposed)
- return;
-
lock (_timerLock)
{
- if (_timerActive)
- {
- _logger.Debug("RestartTimerInactive");
- var interval = GetInactiveTimerIntervalMs();
+ if (_disposed)
+ return;
- if (_timer != null)
- {
- _timer.Change(interval, interval);
- }
- }
+ _volumeRefreshActive = false;
- _timerActive = false;
+ _timer.Change(Timeout.Infinite, Timeout.Infinite);
}
}
+ public void OnPlaybackStartedExternally()
+ {
+ RestartTimer(true);
+ }
+
#region Commanding
- public Task VolumeDown()
+ public Task VolumeDown(CancellationToken cancellationToken)
{
var sendVolume = Math.Max(Volume - 5, 0);
- return SetVolume(sendVolume);
+ return SetVolume(sendVolume, cancellationToken);
}
- public Task VolumeUp()
+ public Task VolumeUp(CancellationToken cancellationToken)
{
var sendVolume = Math.Min(Volume + 5, 100);
- return SetVolume(sendVolume);
+ return SetVolume(sendVolume, cancellationToken);
}
- public Task ToggleMute()
+ public Task ToggleMute(CancellationToken cancellationToken)
{
if (IsMuted)
{
- return Unmute();
+ return Unmute(cancellationToken);
}
- return Mute();
+ return Mute(cancellationToken);
}
- public async Task Mute()
+ public async Task Mute(CancellationToken cancellationToken)
{
- var success = await SetMute(true).ConfigureAwait(true);
+ var success = await SetMute(true, cancellationToken).ConfigureAwait(true);
if (!success)
{
- await SetVolume(0).ConfigureAwait(false);
+ await SetVolume(0, cancellationToken).ConfigureAwait(false);
}
}
- public async Task Unmute()
+ public async Task Unmute(CancellationToken cancellationToken)
{
- var success = await SetMute(false).ConfigureAwait(true);
+ var success = await SetMute(false, cancellationToken).ConfigureAwait(true);
if (!success)
{
var sendVolume = _muteVol <= 0 ? 20 : _muteVol;
- await SetVolume(sendVolume).ConfigureAwait(false);
+ await SetVolume(sendVolume, cancellationToken).ConfigureAwait(false);
}
}
@@ -262,9 +244,11 @@ namespace Emby.Dlna.PlayTo
services.FirstOrDefault(s => (s.ServiceType ?? string.Empty).StartsWith("urn:schemas-upnp-org:service:AVTransport", StringComparison.OrdinalIgnoreCase));
}
- private async Task<bool> SetMute(bool mute)
+ private async Task<bool> SetMute(bool mute, CancellationToken cancellationToken)
{
- var command = RendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetMute");
+ var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ var command = rendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetMute");
if (command == null)
return false;
@@ -278,7 +262,7 @@ namespace Emby.Dlna.PlayTo
_logger.Debug("Setting mute");
var value = mute ? 1 : 0;
- await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType, value))
+ await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value))
.ConfigureAwait(false);
IsMuted = mute;
@@ -289,9 +273,11 @@ namespace Emby.Dlna.PlayTo
/// <summary>
/// Sets volume on a scale of 0-100
/// </summary>
- public async Task SetVolume(int value)
+ public async Task SetVolume(int value, CancellationToken cancellationToken)
{
- var command = RendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetVolume");
+ var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ var command = rendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetVolume");
if (command == null)
return;
@@ -306,13 +292,15 @@ namespace Emby.Dlna.PlayTo
// Remote control will perform better
Volume = value;
- await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType, value))
+ await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType, value))
.ConfigureAwait(false);
}
- public async Task Seek(TimeSpan value)
+ public async Task Seek(TimeSpan value, CancellationToken cancellationToken)
{
- var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "Seek");
+ var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "Seek");
if (command == null)
return;
@@ -323,15 +311,21 @@ namespace Emby.Dlna.PlayTo
throw new InvalidOperationException("Unable to find service");
}
- await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, String.Format("{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME"))
+ await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, String.Format("{0:hh}:{0:mm}:{0:ss}", value), "REL_TIME"))
.ConfigureAwait(false);
+
+ RestartTimer(true);
}
- public async Task SetAvTransport(string url, string header, string metaData)
+ public async Task SetAvTransport(string url, string header, string metaData, CancellationToken cancellationToken)
{
+ var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ url = url.Replace("&", "&amp;");
+
_logger.Debug("{0} - SetAvTransport Uri: {1} DlnaHeaders: {2}", Properties.Name, url, header);
- var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetAVTransportURI");
+ var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetAVTransportURI");
if (command == null)
return;
@@ -348,7 +342,7 @@ namespace Emby.Dlna.PlayTo
throw new InvalidOperationException("Unable to find service");
}
- var post = AvCommands.BuildPost(command, service.ServiceType, url, dictionary);
+ var post = avCommands.BuildPost(command, service.ServiceType, url, dictionary);
await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header)
.ConfigureAwait(false);
@@ -356,7 +350,7 @@ namespace Emby.Dlna.PlayTo
try
{
- await SetPlay().ConfigureAwait(false);
+ await SetPlay(avCommands, CancellationToken.None).ConfigureAwait(false);
}
catch
{
@@ -364,7 +358,7 @@ namespace Emby.Dlna.PlayTo
// Others won't
}
- RestartTimer();
+ RestartTimer(true);
}
private string CreateDidlMeta(string value)
@@ -375,11 +369,11 @@ namespace Emby.Dlna.PlayTo
return DescriptionXmlBuilder.Escape(value);
}
- public async Task SetPlay()
+ private Task SetPlay(TransportCommands avCommands, CancellationToken cancellationToken)
{
- var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "Play");
+ var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "Play");
if (command == null)
- return;
+ return Task.CompletedTask;
var service = GetAvTransportService();
@@ -388,52 +382,74 @@ namespace Emby.Dlna.PlayTo
throw new InvalidOperationException("Unable to find service");
}
- await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, 1))
- .ConfigureAwait(false);
+ return new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1));
}
- public async Task SetStop()
+ public async Task SetPlay(CancellationToken cancellationToken)
{
- var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "Stop");
+ var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ await SetPlay(avCommands, cancellationToken).ConfigureAwait(false);
+
+ RestartTimer(true);
+ }
+
+ public async Task SetStop(CancellationToken cancellationToken)
+ {
+ var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "Stop");
if (command == null)
return;
var service = GetAvTransportService();
- await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, 1))
+ await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1))
.ConfigureAwait(false);
+
+ RestartTimer(true);
}
- public async Task SetPause()
+ public async Task SetPause(CancellationToken cancellationToken)
{
- var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "Pause");
+ var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "Pause");
if (command == null)
return;
var service = GetAvTransportService();
- await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, 1))
+ await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType, 1))
.ConfigureAwait(false);
TransportState = TRANSPORTSTATE.PAUSED;
+
+ RestartTimer(true);
}
#endregion
#region Get data
- private int _successiveStopCount;
private int _connectFailureCount;
private async void TimerCallback(object sender)
{
if (_disposed)
return;
- const int maxSuccessiveStopReturns = 5;
-
try
{
- var transportState = await GetTransportInfo().ConfigureAwait(false);
+ var cancellationToken = CancellationToken.None;
+
+ var avCommands = await GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ if (avCommands == null)
+ {
+ return;
+ }
+
+ var transportState = await GetTransportInfo(avCommands, cancellationToken).ConfigureAwait(false);
if (_disposed)
{
@@ -451,13 +467,13 @@ namespace Emby.Dlna.PlayTo
}
else
{
- var tuple = await GetPositionInfo().ConfigureAwait(false);
+ var tuple = await GetPositionInfo(avCommands, cancellationToken).ConfigureAwait(false);
var currentObject = tuple.Item2;
if (tuple.Item1 && currentObject == null)
{
- currentObject = await GetMediaInfo().ConfigureAwait(false);
+ currentObject = await GetMediaInfo(avCommands, cancellationToken).ConfigureAwait(false);
}
if (currentObject != null)
@@ -474,16 +490,10 @@ namespace Emby.Dlna.PlayTo
// If we're not playing anything make sure we don't get data more often than neccessry to keep the Session alive
if (transportState.Value == TRANSPORTSTATE.STOPPED)
{
- _successiveStopCount++;
-
- if (_successiveStopCount >= maxSuccessiveStopReturns)
- {
- RestartTimerInactive();
- }
+ RestartTimerInactive();
}
else
{
- _successiveStopCount = 0;
RestartTimer();
}
}
@@ -492,54 +502,39 @@ namespace Emby.Dlna.PlayTo
RestartTimerInactive();
}
}
- catch (HttpException ex)
+ catch (Exception ex)
{
if (_disposed)
return;
//_logger.ErrorException("Error updating device info for {0}", ex, Properties.Name);
- _successiveStopCount++;
_connectFailureCount++;
if (_connectFailureCount >= 3)
{
- if (OnDeviceUnavailable != null)
+ var action = OnDeviceUnavailable;
+ if (action != null)
{
_logger.Debug("Disposing device due to loss of connection");
- OnDeviceUnavailable();
+ action();
return;
}
}
- if (_successiveStopCount >= maxSuccessiveStopReturns)
- {
- RestartTimerInactive();
- }
- }
- catch (Exception ex)
- {
- if (_disposed)
- return;
-
- _logger.ErrorException("Error updating device info for {0}", ex, Properties.Name);
-
- _successiveStopCount++;
-
- if (_successiveStopCount >= maxSuccessiveStopReturns)
- {
- RestartTimerInactive();
- }
+ RestartTimerInactive();
}
}
- private async Task GetVolume()
+ private async Task GetVolume(CancellationToken cancellationToken)
{
if (_disposed)
{
return;
}
- var command = RendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetVolume");
+ var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ var command = rendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetVolume");
if (command == null)
return;
@@ -550,7 +545,7 @@ namespace Emby.Dlna.PlayTo
return;
}
- var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType), true)
+ var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), true)
.ConfigureAwait(false);
if (result == null || result.Document == null)
@@ -570,14 +565,16 @@ namespace Emby.Dlna.PlayTo
}
}
- private async Task GetMute()
+ private async Task GetMute(CancellationToken cancellationToken)
{
if (_disposed)
{
return;
}
- var command = RendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMute");
+ var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ var command = rendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMute");
if (command == null)
return;
@@ -588,7 +585,7 @@ namespace Emby.Dlna.PlayTo
return;
}
- var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType), true)
+ var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), true)
.ConfigureAwait(false);
if (result == null || result.Document == null)
@@ -600,9 +597,9 @@ namespace Emby.Dlna.PlayTo
IsMuted = string.Equals(value, "1", StringComparison.OrdinalIgnoreCase);
}
- private async Task<TRANSPORTSTATE?> GetTransportInfo()
+ private async Task<TRANSPORTSTATE?> GetTransportInfo(TransportCommands avCommands, CancellationToken cancellationToken)
{
- var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetTransportInfo");
+ var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetTransportInfo");
if (command == null)
return null;
@@ -610,7 +607,7 @@ namespace Emby.Dlna.PlayTo
if (service == null)
return null;
- var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType), false)
+ var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, avCommands.BuildPost(command, service.ServiceType), false)
.ConfigureAwait(false);
if (result == null || result.Document == null)
@@ -634,9 +631,9 @@ namespace Emby.Dlna.PlayTo
return null;
}
- private async Task<uBaseObject> GetMediaInfo()
+ private async Task<uBaseObject> GetMediaInfo(TransportCommands avCommands, CancellationToken cancellationToken)
{
- var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMediaInfo");
+ var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetMediaInfo");
if (command == null)
return null;
@@ -647,7 +644,9 @@ namespace Emby.Dlna.PlayTo
throw new InvalidOperationException("Unable to find service");
}
- var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType), false)
+ var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), false)
.ConfigureAwait(false);
if (result == null || result.Document == null)
@@ -691,9 +690,9 @@ namespace Emby.Dlna.PlayTo
return null;
}
- private async Task<Tuple<bool, uBaseObject>> GetPositionInfo()
+ private async Task<Tuple<bool, uBaseObject>> GetPositionInfo(TransportCommands avCommands, CancellationToken cancellationToken)
{
- var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetPositionInfo");
+ var command = avCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetPositionInfo");
if (command == null)
return new Tuple<bool, uBaseObject>(false, null);
@@ -704,7 +703,9 @@ namespace Emby.Dlna.PlayTo
throw new InvalidOperationException("Unable to find service");
}
- var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType), false)
+ var rendererCommands = await GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
+
+ var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, rendererCommands.BuildPost(command, service.ServiceType), false)
.ConfigureAwait(false);
if (result == null || result.Document == null)
@@ -831,42 +832,67 @@ namespace Emby.Dlna.PlayTo
#region From XML
- private async Task GetAVProtocolAsync(CancellationToken cancellationToken)
+ private async Task<TransportCommands> GetAVProtocolAsync(CancellationToken cancellationToken)
{
+ var avCommands = AvCommands;
+
+ if (avCommands != null)
+ {
+ return avCommands;
+ }
+
if (_disposed)
{
- return;
+ throw new ObjectDisposedException(GetType().Name);
}
var avService = GetAvTransportService();
if (avService == null)
- return;
+ {
+ return null;
+ }
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
var httpClient = new SsdpHttpClient(_httpClient, _config);
+
var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
- AvCommands = TransportCommands.Create(document);
+ avCommands = TransportCommands.Create(document);
+ AvCommands = avCommands;
+ return avCommands;
}
- private async Task GetRenderingProtocolAsync(CancellationToken cancellationToken)
+ private async Task<TransportCommands> GetRenderingProtocolAsync(CancellationToken cancellationToken)
{
+ var rendererCommands = RendererCommands;
+
+ if (rendererCommands != null)
+ {
+ return rendererCommands;
+ }
+
if (_disposed)
{
- return;
+ throw new ObjectDisposedException(GetType().Name);
}
var avService = GetServiceRenderingControl();
if (avService == null)
- return;
+ {
+ throw new ArgumentException("Device AvService is null");
+ }
+
string url = NormalizeUrl(Properties.BaseUrl, avService.ScpdUrl);
var httpClient = new SsdpHttpClient(_httpClient, _config);
+ _logger.Debug("Dlna Device.GetRenderingProtocolAsync");
var document = await httpClient.GetDataAsync(url, cancellationToken).ConfigureAwait(false);
- RendererCommands = TransportCommands.Create(document);
+ rendererCommands = TransportCommands.Create(document);
+ RendererCommands = rendererCommands;
+ return rendererCommands;
}
private string NormalizeUrl(string baseUrl, string url)
@@ -891,7 +917,7 @@ namespace Emby.Dlna.PlayTo
set;
}
- internal TransportCommands RendererCommands
+ private TransportCommands RendererCommands
{
get;
set;
@@ -985,12 +1011,6 @@ namespace Emby.Dlna.PlayTo
var device = new Device(deviceProperties, httpClient, logger, config, timerFactory);
- if (device.GetAvTransportService() != null)
- {
- await device.GetRenderingProtocolAsync(cancellationToken).ConfigureAwait(false);
- await device.GetAVProtocolAsync(cancellationToken).ConfigureAwait(false);
- }
-
return device;
}
@@ -1010,8 +1030,8 @@ namespace Emby.Dlna.PlayTo
var depth = element.GetDescendantValue(uPnpNamespaces.ud.GetName("depth"));
var url = element.GetDescendantValue(uPnpNamespaces.ud.GetName("url"));
- var widthValue = int.Parse(width, NumberStyles.Any, UsCulture);
- var heightValue = int.Parse(height, NumberStyles.Any, UsCulture);
+ var widthValue = int.Parse(width, NumberStyles.Integer, UsCulture);
+ var heightValue = int.Parse(height, NumberStyles.Integer, UsCulture);
return new DeviceIcon
{
@@ -1089,6 +1109,12 @@ namespace Emby.Dlna.PlayTo
private void OnPlaybackProgress(uBaseObject mediaInfo)
{
+ var mediaUrl = mediaInfo.Url;
+ if (string.IsNullOrWhiteSpace(mediaUrl))
+ {
+ return;
+ }
+
if (PlaybackProgress != null)
{
PlaybackProgress.Invoke(this, new PlaybackProgressEventArgs
@@ -1131,7 +1157,6 @@ namespace Emby.Dlna.PlayTo
_disposed = true;
DisposeTimer();
- GC.SuppressFinalize(this);
}
}