diff options
| -rw-r--r-- | Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs | 2 | ||||
| -rw-r--r-- | Emby.Dlna/Profiles/WdtvLiveProfile.cs | 3 | ||||
| -rw-r--r-- | Emby.Dlna/Profiles/Xml/WDTV Live.xml | 2 | ||||
| -rw-r--r-- | Emby.Dlna/Ssdp/DeviceDiscovery.cs | 46 | ||||
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 7 | ||||
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 1 | ||||
| -rw-r--r-- | Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs | 1 | ||||
| -rw-r--r-- | MediaBrowser.Model/Entities/MetadataProviders.cs | 4 | ||||
| -rw-r--r-- | MediaBrowser.Model/System/IEnvironmentInfo.cs | 3 | ||||
| -rw-r--r-- | MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs | 2 | ||||
| -rw-r--r-- | MediaBrowser.Server.Mono/Program.cs | 13 | ||||
| -rw-r--r-- | MediaBrowser.WebDashboard/Api/DashboardService.cs | 107 | ||||
| -rw-r--r-- | MediaBrowser.WebDashboard/Api/PackageCreator.cs | 50 | ||||
| -rw-r--r-- | MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 8 | ||||
| -rw-r--r-- | RSSDP/SsdpDeviceLocatorBase.cs | 173 |
15 files changed, 150 insertions, 272 deletions
diff --git a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs index dcc974413..5da1ae2dc 100644 --- a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs +++ b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs @@ -12,7 +12,7 @@ namespace Emby.Common.Implementations.EnvironmentInfo public MediaBrowser.Model.System.Architecture? CustomArchitecture { get; set; } public MediaBrowser.Model.System.OperatingSystem? CustomOperatingSystem { get; set; } - public MediaBrowser.Model.System.OperatingSystem OperatingSystem + public virtual MediaBrowser.Model.System.OperatingSystem OperatingSystem { get { diff --git a/Emby.Dlna/Profiles/WdtvLiveProfile.cs b/Emby.Dlna/Profiles/WdtvLiveProfile.cs index 6cef2d965..756882592 100644 --- a/Emby.Dlna/Profiles/WdtvLiveProfile.cs +++ b/Emby.Dlna/Profiles/WdtvLiveProfile.cs @@ -125,8 +125,7 @@ namespace Emby.Dlna.Profiles new DirectPlayProfile { - Container = "flac", - AudioCodec = "flac", + Container = "flac,ac3", Type = DlnaProfileType.Audio }, diff --git a/Emby.Dlna/Profiles/Xml/WDTV Live.xml b/Emby.Dlna/Profiles/Xml/WDTV Live.xml index 1cf3ef597..775d25302 100644 --- a/Emby.Dlna/Profiles/Xml/WDTV Live.xml +++ b/Emby.Dlna/Profiles/Xml/WDTV Live.xml @@ -45,7 +45,7 @@ <DirectPlayProfile container="asf" audioCodec="mp2,ac3" videoCodec="mpeg2video" type="Video" /> <DirectPlayProfile container="mp3" audioCodec="mp2,mp3" type="Audio" /> <DirectPlayProfile container="mp4" audioCodec="mp4" type="Audio" /> - <DirectPlayProfile container="flac" audioCodec="flac" type="Audio" /> + <DirectPlayProfile container="flac,ac3" type="Audio" /> <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" /> <DirectPlayProfile container="ogg" audioCodec="vorbis" type="Audio" /> <DirectPlayProfile container="jpeg,png,gif,bmp,tiff" type="Photo" /> diff --git a/Emby.Dlna/Ssdp/DeviceDiscovery.cs b/Emby.Dlna/Ssdp/DeviceDiscovery.cs index 7852669c9..bd5ad31c2 100644 --- a/Emby.Dlna/Ssdp/DeviceDiscovery.cs +++ b/Emby.Dlna/Ssdp/DeviceDiscovery.cs @@ -19,13 +19,12 @@ using Rssdp.Infrastructure; namespace Emby.Dlna.Ssdp { - public class DeviceDiscovery : IDeviceDiscovery, IDisposable + public class DeviceDiscovery : IDeviceDiscovery { private bool _disposed; private readonly ILogger _logger; private readonly IServerConfigurationManager _config; - private readonly CancellationTokenSource _tokenSource; public event EventHandler<GenericEventArgs<UpnpDeviceInfo>> DeviceDiscovered; public event EventHandler<GenericEventArgs<UpnpDeviceInfo>> DeviceLeft; @@ -37,8 +36,6 @@ namespace Emby.Dlna.Ssdp public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, ISocketFactory socketFactory, ITimerFactory timerFactory) { - _tokenSource = new CancellationTokenSource(); - _logger = logger; _config = config; _socketFactory = socketFactory; @@ -59,39 +56,10 @@ namespace Emby.Dlna.Ssdp _deviceLocator.DeviceAvailable += deviceLocator_DeviceAvailable; _deviceLocator.DeviceUnavailable += _DeviceLocator_DeviceUnavailable; - // Perform a search so we don't have to wait for devices to broadcast notifications - // again to get any results right away (notifications are broadcast periodically). - StartAsyncSearch(); - } - - private void StartAsyncSearch() - { - Task.Factory.StartNew(async (o) => - { - while (!_tokenSource.IsCancellationRequested) - { - try - { - // Enable listening for notifications (optional) - _deviceLocator.StartListeningForNotifications(); - - await _deviceLocator.SearchAsync(_tokenSource.Token).ConfigureAwait(false); + var dueTime = TimeSpan.FromSeconds(5); + var interval = TimeSpan.FromSeconds(_config.GetDlnaConfiguration().ClientDiscoveryIntervalSeconds); - var delay = _config.GetDlnaConfiguration().ClientDiscoveryIntervalSeconds * 1000; - - await Task.Delay(delay, _tokenSource.Token).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error searching for devices", ex); - } - } - - }, CancellationToken.None, TaskCreationOptions.LongRunning); + _deviceLocator.RestartBroadcastTimer(dueTime, interval); } // Process each found device in the event handler @@ -141,7 +109,11 @@ namespace Emby.Dlna.Ssdp if (!_disposed) { _disposed = true; - _tokenSource.Cancel(); + if (_deviceLocator != null) + { + _deviceLocator.Dispose(); + _deviceLocator = null; + } } } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 89ef87c8e..1ec5dd1d5 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -2092,13 +2092,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV writer.WriteElementString("credits", person); } - var rt = item.GetProviderId(MetadataProviders.RottenTomatoes); - - if (!string.IsNullOrEmpty(rt)) - { - writer.WriteElementString("rottentomatoesid", rt); - } - var tmdbCollection = item.GetProviderId(MetadataProviders.TmdbCollection); if (!string.IsNullOrEmpty(tmdbCollection)) diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index e59a8f93c..613a30b1d 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -365,7 +365,6 @@ namespace Emby.Server.Implementations.LiveTv } } - _logger.Info("Live stream info: {0}", _jsonSerializer.SerializeToString(info)); Normalize(info, service, isVideo); return new Tuple<MediaSourceInfo, IDirectStreamProvider>(info, directStreamProvider); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index dd95660c7..747e0fdd3 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -154,6 +154,7 @@ namespace Emby.Server.Implementations.LiveTv _logger.ErrorException("Error probing live tv stream", ex); } + _logger.Info("Live stream info: {0}", _jsonSerializer.SerializeToString(stream)); return new Tuple<MediaSourceInfo, IDirectStreamProvider>(stream, directStreamProvider); } diff --git a/MediaBrowser.Model/Entities/MetadataProviders.cs b/MediaBrowser.Model/Entities/MetadataProviders.cs index 1e7bde934..efd4339d5 100644 --- a/MediaBrowser.Model/Entities/MetadataProviders.cs +++ b/MediaBrowser.Model/Entities/MetadataProviders.cs @@ -24,10 +24,6 @@ namespace MediaBrowser.Model.Entities /// </summary> Tvcom = 5, /// <summary> - /// The rotten tomatoes - /// </summary> - RottenTomatoes = 6, - /// <summary> /// Tmdb Collection Id /// </summary> TmdbCollection = 7, diff --git a/MediaBrowser.Model/System/IEnvironmentInfo.cs b/MediaBrowser.Model/System/IEnvironmentInfo.cs index abe39fa03..2c57df97c 100644 --- a/MediaBrowser.Model/System/IEnvironmentInfo.cs +++ b/MediaBrowser.Model/System/IEnvironmentInfo.cs @@ -17,6 +17,7 @@ namespace MediaBrowser.Model.System { Windows, Linux, - OSX + OSX, + BSD } } diff --git a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs index 3f969b609..96eab63cd 100644 --- a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs @@ -142,7 +142,7 @@ namespace MediaBrowser.Providers.Music if (fileInfo.Exists) { - if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 7) + if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 3) { return _cachedTask; } diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 8100dec8d..4790378a9 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -319,5 +319,18 @@ namespace MediaBrowser.Server.Mono { return Syscall.getuid().ToString(CultureInfo.InvariantCulture); } + + public override Model.System.OperatingSystem OperatingSystem + { + get + { + if (IsBsd) + { + return Model.System.OperatingSystem.BSD; + } + + return base.OperatingSystem; + } + } } } diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 91c23f871..c6cdeb354 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -139,6 +139,23 @@ namespace MediaBrowser.WebDashboard.Api _memoryStreamFactory = memoryStreamFactory; } + /// <summary> + /// Gets the dashboard UI path. + /// </summary> + /// <value>The dashboard UI path.</value> + public string DashboardUIPath + { + get + { + if (!string.IsNullOrEmpty(_serverConfigurationManager.Configuration.DashboardSourcePath)) + { + return _serverConfigurationManager.Configuration.DashboardSourcePath; + } + + return Path.Combine(_serverConfigurationManager.ApplicationPaths.ApplicationResourcesPath, "dashboard-ui"); + } + } + public object Get(GetFavIcon request) { return Get(new GetDashboardResource @@ -176,7 +193,7 @@ namespace MediaBrowser.WebDashboard.Api if (plugin != null && stream != null) { - return _resultFactory.GetStaticResult(Request, plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator().ModifyHtml("dummy.html", stream, null, _appHost.ApplicationVersion.ToString(), null)); + return _resultFactory.GetStaticResult(Request, plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator(DashboardUIPath).ModifyHtml("dummy.html", stream, null, _appHost.ApplicationVersion.ToString(), null)); } throw new ResourceNotFoundException(); @@ -274,9 +291,11 @@ namespace MediaBrowser.WebDashboard.Api path = path.Replace("bower_components" + _appHost.ApplicationVersion, "bower_components", StringComparison.OrdinalIgnoreCase); var contentType = MimeTypes.GetMimeType(path); + var basePath = DashboardUIPath; // Bounce them to the startup wizard if it hasn't been completed yet - if (!_serverConfigurationManager.Configuration.IsStartupWizardCompleted && path.IndexOf("wizard", StringComparison.OrdinalIgnoreCase) == -1 && GetPackageCreator().IsCoreHtml(path)) + if (!_serverConfigurationManager.Configuration.IsStartupWizardCompleted && + path.IndexOf("wizard", StringComparison.OrdinalIgnoreCase) == -1 && GetPackageCreator(basePath).IsCoreHtml(path)) { // But don't redirect if an html import is being requested. if (path.IndexOf("bower_components", StringComparison.OrdinalIgnoreCase) == -1) @@ -296,7 +315,7 @@ namespace MediaBrowser.WebDashboard.Api !contentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase) && !contentType.StartsWith("font/", StringComparison.OrdinalIgnoreCase)) { - var stream = await GetResourceStream(path, localizationCulture).ConfigureAwait(false); + var stream = await GetResourceStream(basePath, path, localizationCulture).ConfigureAwait(false); return _resultFactory.GetResult(stream, contentType); } @@ -311,7 +330,7 @@ namespace MediaBrowser.WebDashboard.Api var cacheKey = (_appHost.ApplicationVersion + (localizationCulture ?? string.Empty) + path).GetMD5(); - return await _resultFactory.GetStaticResult(Request, cacheKey, null, cacheDuration, contentType, () => GetResourceStream(path, localizationCulture)).ConfigureAwait(false); + return await _resultFactory.GetStaticResult(Request, cacheKey, null, cacheDuration, contentType, () => GetResourceStream(basePath, path, localizationCulture)).ConfigureAwait(false); } private string GetLocalizationCulture() @@ -322,86 +341,72 @@ namespace MediaBrowser.WebDashboard.Api /// <summary> /// Gets the resource stream. /// </summary> - /// <param name="path">The path.</param> - /// <param name="localizationCulture">The localization culture.</param> - /// <returns>Task{Stream}.</returns> - private Task<Stream> GetResourceStream(string path, string localizationCulture) + private Task<Stream> GetResourceStream(string basePath, string virtualPath, string localizationCulture) { - return GetPackageCreator() - .GetResource(path, null, localizationCulture, _appHost.ApplicationVersion.ToString()); + return GetPackageCreator(basePath) + .GetResource(virtualPath, null, localizationCulture, _appHost.ApplicationVersion.ToString()); } - private PackageCreator GetPackageCreator() + private PackageCreator GetPackageCreator(string basePath) { - return new PackageCreator(_fileSystem, _logger, _serverConfigurationManager, _memoryStreamFactory); + return new PackageCreator(basePath, _fileSystem, _logger, _serverConfigurationManager, _memoryStreamFactory); } public async Task<object> Get(GetDashboardPackage request) { var mode = request.Mode; - var path = !string.IsNullOrWhiteSpace(mode) ? - Path.Combine(_serverConfigurationManager.ApplicationPaths.ProgramDataPath, "webclient-dump") + var inputPath = string.IsNullOrWhiteSpace(mode) ? + DashboardUIPath + : "C:\\dev\\emby-web-mobile-master\\dist"; + + var targetPath = !string.IsNullOrWhiteSpace(mode) ? + inputPath : "C:\\dev\\emby-web-mobile\\src"; - try - { - _fileSystem.DeleteDirectory(path, true); - } - catch (IOException) - { + var packageCreator = GetPackageCreator(inputPath); - } + if (!string.Equals(inputPath, targetPath, StringComparison.OrdinalIgnoreCase)) + { + try + { + _fileSystem.DeleteDirectory(targetPath, true); + } + catch (IOException) + { - var creator = GetPackageCreator(); + } - CopyDirectory(creator.DashboardUIPath, path); + CopyDirectory(inputPath, targetPath); + } string culture = null; var appVersion = _appHost.ApplicationVersion.ToString(); - // Try to trim the output size a bit - var bowerPath = Path.Combine(path, "bower_components"); - - if (!string.IsNullOrWhiteSpace(mode)) - { - // Delete things that are unneeded in an attempt to keep the output as trim as possible - - DeleteFoldersByName(Path.Combine(bowerPath, "emby-webcomponents", "fonts"), "roboto"); - _fileSystem.DeleteDirectory(Path.Combine(path, "css", "images", "tour"), true); - } - - await DumpHtml(creator.DashboardUIPath, path, mode, culture, appVersion); + await DumpHtml(packageCreator, inputPath, targetPath, mode, culture, appVersion); return ""; } - private void DeleteFoldersByName(string path, string name) - { - var directories = _fileSystem.GetDirectories(path, true) - .Where(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)) - .ToList(); - - foreach (var directory in directories) - { - _fileSystem.DeleteDirectory(directory.FullName, true); - } - } - - private async Task DumpHtml(string source, string destination, string mode, string culture, string appVersion) + private async Task DumpHtml(PackageCreator packageCreator, string source, string destination, string mode, string culture, string appVersion) { foreach (var file in _fileSystem.GetFiles(source)) { var filename = file.Name; - await DumpFile(filename, Path.Combine(destination, filename), mode, culture, appVersion).ConfigureAwait(false); + if (!string.Equals(file.Extension, ".html", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + await DumpFile(packageCreator, filename, Path.Combine(destination, filename), mode, culture, appVersion).ConfigureAwait(false); } } - private async Task DumpFile(string resourceVirtualPath, string destinationFilePath, string mode, string culture, string appVersion) + private async Task DumpFile(PackageCreator packageCreator, string resourceVirtualPath, string destinationFilePath, string mode, string culture, string appVersion) { - using (var stream = await GetPackageCreator().GetResource(resourceVirtualPath, mode, culture, appVersion).ConfigureAwait(false)) + using (var stream = await packageCreator.GetResource(resourceVirtualPath, mode, culture, appVersion).ConfigureAwait(false)) { using (var fs = _fileSystem.GetFileStream(destinationFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) { diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs index 453f46edd..f124b6e4b 100644 --- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs +++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs @@ -19,31 +19,33 @@ namespace MediaBrowser.WebDashboard.Api private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly IMemoryStreamFactory _memoryStreamFactory; + private readonly string _basePath; - public PackageCreator(IFileSystem fileSystem, ILogger logger, IServerConfigurationManager config, IMemoryStreamFactory memoryStreamFactory) + public PackageCreator(string basePath, IFileSystem fileSystem, ILogger logger, IServerConfigurationManager config, IMemoryStreamFactory memoryStreamFactory) { _fileSystem = fileSystem; _logger = logger; _config = config; _memoryStreamFactory = memoryStreamFactory; + _basePath = basePath; } - public async Task<Stream> GetResource(string path, + public async Task<Stream> GetResource(string virtualPath, string mode, string localizationCulture, string appVersion) { - var resourceStream = GetRawResourceStream(path); + var resourceStream = GetRawResourceStream(virtualPath); if (resourceStream != null) { // Don't apply any caching for html pages // jQuery ajax doesn't seem to handle if-modified-since correctly - if (IsFormat(path, "html")) + if (IsFormat(virtualPath, "html")) { - if (IsCoreHtml(path)) + if (IsCoreHtml(virtualPath)) { - resourceStream = await ModifyHtml(path, resourceStream, mode, appVersion, localizationCulture).ConfigureAwait(false); + resourceStream = await ModifyHtml(virtualPath, resourceStream, mode, appVersion, localizationCulture).ConfigureAwait(false); } } } @@ -63,32 +65,12 @@ namespace MediaBrowser.WebDashboard.Api } /// <summary> - /// Gets the dashboard UI path. - /// </summary> - /// <value>The dashboard UI path.</value> - public string DashboardUIPath - { - get - { - if (!string.IsNullOrEmpty(_config.Configuration.DashboardSourcePath)) - { - return _config.Configuration.DashboardSourcePath; - } - - return Path.Combine(_config.ApplicationPaths.ApplicationResourcesPath, "dashboard-ui"); - } - } - - /// <summary> /// Gets the dashboard resource path. /// </summary> - /// <param name="virtualPath">The virtual path.</param> /// <returns>System.String.</returns> private string GetDashboardResourcePath(string virtualPath) { - var rootPath = DashboardUIPath; - - var fullPath = Path.Combine(rootPath, virtualPath.Replace('/', _fileSystem.DirectorySeparatorChar)); + var fullPath = Path.Combine(_basePath, virtualPath.Replace('/', _fileSystem.DirectorySeparatorChar)); try { @@ -100,7 +82,7 @@ namespace MediaBrowser.WebDashboard.Api } // Don't allow file system access outside of the source folder - if (!_fileSystem.ContainsSubPath(rootPath, fullPath)) + if (!_fileSystem.ContainsSubPath(_basePath, fullPath)) { throw new SecurityException("Access denied"); } @@ -118,10 +100,8 @@ namespace MediaBrowser.WebDashboard.Api path = GetDashboardResourcePath(path); var parent = Path.GetDirectoryName(path); - var basePath = DashboardUIPath; - - return string.Equals(basePath, parent, StringComparison.OrdinalIgnoreCase) || - string.Equals(Path.Combine(basePath, "voice"), parent, StringComparison.OrdinalIgnoreCase); + return string.Equals(_basePath, parent, StringComparison.OrdinalIgnoreCase) || + string.Equals(Path.Combine(_basePath, "voice"), parent, StringComparison.OrdinalIgnoreCase); } /// <summary> @@ -319,11 +299,9 @@ namespace MediaBrowser.WebDashboard.Api /// <summary> /// Gets the raw resource stream. /// </summary> - /// <param name="path">The path.</param> - /// <returns>Task{Stream}.</returns> - private Stream GetRawResourceStream(string path) + private Stream GetRawResourceStream(string virtualPath) { - return _fileSystem.GetFileStream(GetDashboardResourcePath(path), FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite, true); + return _fileSystem.GetFileStream(GetDashboardResourcePath(virtualPath), FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite, true); } } diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 4f7715874..5a1c7bf13 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -579,14 +579,6 @@ namespace MediaBrowser.XbmcMetadata.Savers writer.WriteElementString("website", item.HomePageUrl); } - var rt = item.GetProviderId(MetadataProviders.RottenTomatoes); - - if (!string.IsNullOrEmpty(rt)) - { - writer.WriteElementString("rottentomatoesid", rt); - writtenProviderIds.Add(MetadataProviders.RottenTomatoes.ToString()); - } - var tmdbCollection = item.GetProviderId(MetadataProviders.TmdbCollection); if (!string.IsNullOrEmpty(tmdbCollection)) diff --git a/RSSDP/SsdpDeviceLocatorBase.cs b/RSSDP/SsdpDeviceLocatorBase.cs index 4f5eae616..1adb95cdf 100644 --- a/RSSDP/SsdpDeviceLocatorBase.cs +++ b/RSSDP/SsdpDeviceLocatorBase.cs @@ -24,11 +24,9 @@ namespace Rssdp.Infrastructure private List<DiscoveredSsdpDevice> _Devices; private ISsdpCommunicationsServer _CommunicationsServer; - private IList<DiscoveredSsdpDevice> _SearchResults; - private object _SearchResultsSynchroniser; - - private ITimer _ExpireCachedDevicesTimer; + private ITimer _BroadcastTimer; private ITimerFactory _timerFactory; + private object _timerLock = new object(); private static readonly TimeSpan DefaultSearchWaitTime = TimeSpan.FromSeconds(4); private static readonly TimeSpan OneSecond = TimeSpan.FromSeconds(1); @@ -48,7 +46,6 @@ namespace Rssdp.Infrastructure _timerFactory = timerFactory; _CommunicationsServer.ResponseReceived += CommsServer_ResponseReceived; - _SearchResultsSynchroniser = new object(); _Devices = new List<DiscoveredSsdpDevice>(); } @@ -92,11 +89,52 @@ namespace Rssdp.Infrastructure #region Search Overloads + public void RestartBroadcastTimer(TimeSpan dueTime, TimeSpan period) + { + lock (_timerLock) + { + if (_BroadcastTimer == null) + { + _BroadcastTimer = _timerFactory.Create(OnBroadcastTimerCallback, null, dueTime, period); + } + else + { + _BroadcastTimer.Change(dueTime, period); + } + } + } + + public void DisposeBroadcastTimer() + { + lock (_timerLock) + { + if (_BroadcastTimer != null) + { + _BroadcastTimer.Dispose(); + _BroadcastTimer = null; + } + } + } + + private async void OnBroadcastTimerCallback(object state) + { + StartListeningForNotifications(); + RemoveExpiredDevicesFromCache(); + + try + { + await SearchAsync(CancellationToken.None).ConfigureAwait(false); + } + catch (Exception ex) + { + + } + } + /// <summary> /// Performs a search for all devices using the default search timeout. /// </summary> - /// <returns>A task whose result is an <see cref="IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns> - public Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(CancellationToken cancellationToken) + private Task SearchAsync(CancellationToken cancellationToken) { return SearchAsync(SsdpConstants.SsdpDiscoverAllSTHeader, DefaultSearchWaitTime, cancellationToken); } @@ -111,8 +149,7 @@ namespace Rssdp.Infrastructure /// <item><term>Device type</term><description>Fully qualified device type starting with urn: i.e urn:schemas-upnp-org:Basic:1</description></item> /// </list> /// </param> - /// <returns>A task whose result is an <see cref="IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns> - public Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(string searchTarget) + private Task SearchAsync(string searchTarget) { return SearchAsync(searchTarget, DefaultSearchWaitTime, CancellationToken.None); } @@ -121,13 +158,12 @@ namespace Rssdp.Infrastructure /// Performs a search for all devices using the specified search timeout. /// </summary> /// <param name="searchWaitTime">The amount of time to wait for network responses to the search request. Longer values will likely return more devices, but increase search time. A value between 1 and 5 seconds is recommended by the UPnP 1.1 specification, this method requires the value be greater 1 second if it is not zero. Specify TimeSpan.Zero to return only devices already in the cache.</param> - /// <returns>A task whose result is an <see cref="IEnumerable{T}"/> of <see cref="DiscoveredSsdpDevice" /> instances, representing all found devices.</returns> - public Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(TimeSpan searchWaitTime) + private Task SearchAsync(TimeSpan searchWaitTime) { return SearchAsync(SsdpConstants.SsdpDiscoverAllSTHeader, searchWaitTime, CancellationToken.None); } - public async Task<IEnumerable<DiscoveredSsdpDevice>> SearchAsync(string searchTarget, TimeSpan searchWaitTime, CancellationToken cancellationToken) + private Task SearchAsync(string searchTarget, TimeSpan searchWaitTime, CancellationToken cancellationToken) { if (searchTarget == null) throw new ArgumentNullException("searchTarget"); if (searchTarget.Length == 0) throw new ArgumentException("searchTarget cannot be an empty string.", "searchTarget"); @@ -136,48 +172,7 @@ namespace Rssdp.Infrastructure ThrowIfDisposed(); - if (_SearchResults != null) throw new InvalidOperationException("Search already in progress. Only one search at a time is allowed."); - _SearchResults = new List<DiscoveredSsdpDevice>(); - - // If searchWaitTime == 0 then we are only going to report unexpired cached items, not actually do a search. - if (searchWaitTime > TimeSpan.Zero) - await BroadcastDiscoverMessage(searchTarget, SearchTimeToMXValue(searchWaitTime), cancellationToken).ConfigureAwait(false); - - lock (_SearchResultsSynchroniser) - { - foreach (var device in GetUnexpiredDevices().Where(NotificationTypeMatchesFilter)) - { - DeviceFound(device, false, null); - } - } - - if (searchWaitTime != TimeSpan.Zero) - await Task.Delay(searchWaitTime, cancellationToken).ConfigureAwait(false); - - IEnumerable<DiscoveredSsdpDevice> retVal = null; - - try - { - lock (_SearchResultsSynchroniser) - { - retVal = _SearchResults; - _SearchResults = null; - } - - RemoveExpiredDevicesFromCache(); - } - finally - { - var server = _CommunicationsServer; - try - { - if (server != null) // In case we were disposed while searching. - server.StopListeningForResponses(); - } - catch (ObjectDisposedException) { } - } - - return retVal; + return BroadcastDiscoverMessage(searchTarget, SearchTimeToMXValue(searchWaitTime), cancellationToken); } #endregion @@ -287,9 +282,7 @@ namespace Rssdp.Infrastructure if (disposing) { - var timer = _ExpireCachedDevicesTimer; - if (timer != null) - timer.Dispose(); + DisposeBroadcastTimer(); var commsServer = _CommunicationsServer; _CommunicationsServer = null; @@ -332,40 +325,9 @@ namespace Rssdp.Infrastructure private void DeviceFound(DiscoveredSsdpDevice device, bool isNewDevice, IpAddressInfo localIpAddress) { - // Don't raise the event if we've already done it for a cached - // version of this device, and the cached version isn't - // "significantly" different, i.e location and cachelifetime - // haven't changed. - var raiseEvent = false; - if (!NotificationTypeMatchesFilter(device)) return; - lock (_SearchResultsSynchroniser) - { - if (_SearchResults != null) - { - var existingDevice = FindExistingDeviceNotification(_SearchResults, device.NotificationType, device.Usn); - if (existingDevice == null) - { - _SearchResults.Add(device); - raiseEvent = true; - } - else - { - if (existingDevice.DescriptionLocation != device.DescriptionLocation || existingDevice.CacheLifetime != device.CacheLifetime) - { - _SearchResults.Remove(existingDevice); - _SearchResults.Add(device); - raiseEvent = true; - } - } - } - else - raiseEvent = true; - } - - if (raiseEvent) - OnDeviceAvailable(device, isNewDevice, localIpAddress); + OnDeviceAvailable(device, isNewDevice, localIpAddress); } private bool NotificationTypeMatchesFilter(DiscoveredSsdpDevice device) @@ -450,8 +412,6 @@ namespace Rssdp.Infrastructure }; AddOrUpdateDiscoveredDevice(device, localIpAddress); - - ResetExpireCachedDevicesTimer(); } } @@ -477,26 +437,9 @@ namespace Rssdp.Infrastructure if (NotificationTypeMatchesFilter(deadDevice)) OnDeviceUnavailable(deadDevice, false); } - - ResetExpireCachedDevicesTimer(); } } - private void ResetExpireCachedDevicesTimer() - { - if (IsDisposed) return; - - if (_ExpireCachedDevicesTimer == null) - _ExpireCachedDevicesTimer = _timerFactory.Create(this.ExpireCachedDevices, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); - - _ExpireCachedDevicesTimer.Change(60000, System.Threading.Timeout.Infinite); - } - - private void ExpireCachedDevices(object state) - { - RemoveExpiredDevicesFromCache(); - } - #region Header/Message Processing Utilities private static string GetFirstHeaderStringValue(string headerName, HttpResponseMessage message) @@ -624,20 +567,6 @@ namespace Rssdp.Infrastructure if (existingDevices != null && existingDevices.Any()) { - lock (_SearchResultsSynchroniser) - { - if (_SearchResults != null) - { - var resultsToRemove = (from result in _SearchResults where result.Usn == deviceUsn select result).ToArray(); - foreach (var result in resultsToRemove) - { - if (this.IsDisposed) return true; - - _SearchResults.Remove(result); - } - } - } - foreach (var removedDevice in existingDevices) { if (NotificationTypeMatchesFilter(removedDevice)) |
