diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index 8fdfea6b41..4e88e946f4 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Net; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; @@ -46,6 +45,11 @@ namespace MediaBrowser.Api /// true if [include hidden]; otherwise, false. [ApiMember(Name = "IncludeHidden", Description = "An optional filter to include or exclude hidden files and folders. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] public bool IncludeHidden { get; set; } + + public GetDirectoryContents() + { + IncludeHidden = true; + } } [Route("/Environment/NetworkShares", "GET", Summary = "Gets shares from a network device")] diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 9e2e399d78..bb7f6bb1e9 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -2192,7 +2192,7 @@ namespace MediaBrowser.Api.Playback { if (string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase)) { - inputModifier += " -noaccurate_seek"; + //inputModifier += " -noaccurate_seek"; } } diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 3b577ac01e..2bf61f90bd 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -141,10 +141,10 @@ namespace MediaBrowser.Api.Playback var profile = request.DeviceProfile; - var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); - if (caps != null) + if (profile == null) { - if (profile == null) + var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); + if (caps != null) { profile = caps.DeviceProfile; } diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index afe3da7106..b05a1bd209 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -66,13 +66,12 @@ namespace MediaBrowser.Api { _config.Configuration.IsStartupWizardCompleted = true; _config.Configuration.EnableLocalizedGuids = true; - _config.Configuration.MergeMetadataAndImagesByName = true; - _config.Configuration.EnableStandaloneMetadata = true; _config.Configuration.EnableLibraryMetadataSubFolder = true; _config.Configuration.EnableCustomPathSubFolders = true; _config.Configuration.DisableStartupScan = true; _config.Configuration.EnableUserViews = true; _config.Configuration.EnableDateLastRefresh = true; + _config.Configuration.MergeMetadataAndImagesByName = true; _config.SaveConfiguration(); } diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs index 7002a37035..08c6b0ba47 100644 --- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs +++ b/MediaBrowser.Api/UserLibrary/PlaystateService.cs @@ -370,6 +370,8 @@ namespace MediaBrowser.Api.UserLibrary public void Post(ReportPlaybackStopped request) { + Logger.Debug("ReportPlaybackStopped PlaySessionId: {0}", request.PlaySessionId ?? string.Empty); + if (!string.IsNullOrWhiteSpace(request.PlaySessionId)) { ApiEntryPoint.Instance.KillTranscodingJobs(AuthorizationContext.GetAuthorizationInfo(Request).DeviceId, request.PlaySessionId, s => true); diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs index bc3dc360f7..ff11c889a6 100644 --- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; -using System.Threading; using MoreLinq; namespace MediaBrowser.Common.Implementations.Networking @@ -14,22 +13,11 @@ namespace MediaBrowser.Common.Implementations.Networking public abstract class BaseNetworkManager { protected ILogger Logger { get; private set; } - private Timer _clearCacheTimer; + private DateTime _lastRefresh; protected BaseNetworkManager(ILogger logger) { Logger = logger; - - // Can't use network change events due to a crash in Linux - _clearCacheTimer = new Timer(ClearCacheTimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); - } - - private void ClearCacheTimerCallback(object state) - { - lock (_localIpAddressSyncLock) - { - _localIpAddresses = null; - } } private volatile List _localIpAddresses; @@ -41,15 +29,21 @@ namespace MediaBrowser.Common.Implementations.Networking /// IPAddress. public IEnumerable GetLocalIpAddresses() { - if (_localIpAddresses == null) + const int cacheMinutes = 3; + var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes; + + if (_localIpAddresses == null || forceRefresh) { lock (_localIpAddressSyncLock) { - if (_localIpAddresses == null) + forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes; + + if (_localIpAddresses == null || forceRefresh) { var addresses = GetLocalIpAddressesInternal().ToList(); _localIpAddresses = addresses; + _lastRefresh = DateTime.UtcNow; return addresses; } diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 95f29915db..a4ccbb6f84 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -233,7 +233,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// /// The _triggers /// - private IEnumerable _triggers; + private volatile List _triggers; /// /// The _triggers sync lock /// @@ -532,7 +532,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// Loads the triggers. /// /// IEnumerable{BaseTaskTrigger}. - private IEnumerable LoadTriggers() + private List LoadTriggers() { try { @@ -543,12 +543,12 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks catch (FileNotFoundException) { // File doesn't exist. No biggie. Return defaults. - return ScheduledTask.GetDefaultTriggers(); + return ScheduledTask.GetDefaultTriggers().ToList(); } catch (DirectoryNotFoundException) { // File doesn't exist. No biggie. Return defaults. - return ScheduledTask.GetDefaultTriggers(); + return ScheduledTask.GetDefaultTriggers().ToList(); } } diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index ccdb319fee..17f211d848 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -90,6 +90,7 @@ + diff --git a/MediaBrowser.Common/Threading/PeriodicTimer.cs b/MediaBrowser.Common/Threading/PeriodicTimer.cs new file mode 100644 index 0000000000..75ccada4ef --- /dev/null +++ b/MediaBrowser.Common/Threading/PeriodicTimer.cs @@ -0,0 +1,72 @@ +using System; +using System.Threading; +using Microsoft.Win32; + +namespace MediaBrowser.Common.Threading +{ + public class PeriodicTimer : IDisposable + { + public Action Callback { get; set; } + private Timer _timer; + private readonly object _state; + private readonly object _timerLock = new object(); + private readonly TimeSpan _period; + + public PeriodicTimer(Action callback, object state, TimeSpan dueTime, TimeSpan period) + { + if (callback == null) + { + throw new ArgumentNullException("callback"); + } + + Callback = callback; + _period = period; + _state = state; + + StartTimer(dueTime); + } + + void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) + { + if (e.Mode == PowerModes.Resume) + { + DisposeTimer(); + StartTimer(Timeout.InfiniteTimeSpan); + } + } + + private void TimerCallback(object state) + { + Callback(state); + } + + private void StartTimer(TimeSpan dueTime) + { + lock (_timerLock) + { + _timer = new Timer(TimerCallback, _state, dueTime, _period); + + SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; + } + } + + private void DisposeTimer() + { + SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; + + lock (_timerLock) + { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } + } + } + + public void Dispose() + { + DisposeTimer(); + } + } +} diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 98d1eb4ce2..654c9abd3f 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -1,17 +1,21 @@ -using MediaBrowser.Controller.Providers; +using System; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Users; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Library; namespace MediaBrowser.Controller.Entities.Audio { /// /// Class MusicAlbum /// - public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo + public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo, IMetadataContainer { public MusicAlbum() { @@ -139,5 +143,58 @@ namespace MediaBrowser.Controller.Entities.Audio return id; } + + public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress progress, CancellationToken cancellationToken) + { + var items = GetRecursiveChildren().ToList(); + + var songs = items.OfType