aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-02-01 14:24:15 -0500
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-02-01 14:24:15 -0500
commit37352785acef4db99301c1e88624cf48133ec979 (patch)
tree15638d697cc56a0a774bf261de9814c9034f8e42 /MediaBrowser.Server.Implementations
parentf14e9b8d3af98f6ffbe243b105f96f46e8cf3b06 (diff)
parentf5ebeddbf5104092ce584486689af6640125054f (diff)
Merge branch 'beta'
Diffstat (limited to 'MediaBrowser.Server.Implementations')
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs61
-rw-r--r--MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs12
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs5
-rw-r--r--MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs13
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs5
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs5
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs16
-rw-r--r--MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs233
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs34
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs19
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs42
-rw-r--r--MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs12
-rw-r--r--MediaBrowser.Server.Implementations/Library/LibraryManager.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs13
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserViewManager.cs9
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs100
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs2
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs37
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs1
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/ca.json22
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Core/nl.json4
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj4
-rw-r--r--MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs6
-rw-r--r--MediaBrowser.Server.Implementations/packages.config2
24 files changed, 360 insertions, 301 deletions
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index b115c3bfd..284556c72 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -29,7 +29,7 @@ using CommonIO;
namespace MediaBrowser.Server.Implementations.Channels
{
- public class ChannelManager : IChannelManager, IDisposable
+ public class ChannelManager : IChannelManager
{
private IChannel[] _channels;
@@ -47,11 +47,6 @@ namespace MediaBrowser.Server.Implementations.Channels
private readonly ILocalizationManager _localization;
private readonly ConcurrentDictionary<Guid, bool> _refreshedItems = new ConcurrentDictionary<Guid, bool>();
- private readonly ConcurrentDictionary<string, int> _downloadCounts = new ConcurrentDictionary<string, int>();
-
- private Timer _refreshTimer;
- private Timer _clearDownloadCountsTimer;
-
public ChannelManager(IUserManager userManager, IDtoService dtoService, ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IUserDataManager userDataManager, IJsonSerializer jsonSerializer, ILocalizationManager localization, IHttpClient httpClient, IProviderManager providerManager)
{
_userManager = userManager;
@@ -65,9 +60,6 @@ namespace MediaBrowser.Server.Implementations.Channels
_localization = localization;
_httpClient = httpClient;
_providerManager = providerManager;
-
- _refreshTimer = new Timer(s => _refreshedItems.Clear(), null, TimeSpan.FromHours(3), TimeSpan.FromHours(3));
- _clearDownloadCountsTimer = new Timer(s => _downloadCounts.Clear(), null, TimeSpan.FromHours(24), TimeSpan.FromHours(24));
}
private TimeSpan CacheLength
@@ -206,6 +198,8 @@ namespace MediaBrowser.Server.Implementations.Channels
public async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
{
+ _refreshedItems.Clear();
+
var allChannelsList = GetAllChannels().ToList();
var numComplete = 0;
@@ -1471,12 +1465,6 @@ namespace MediaBrowser.Server.Implementations.Channels
var limit = features.DailyDownloadLimit;
- if (!ValidateDownloadLimit(host, limit))
- {
- _logger.Error(string.Format("Download limit has been reached for {0}", channel.Name));
- throw new ChannelDownloadException(string.Format("Download limit has been reached for {0}", channel.Name));
- }
-
foreach (var header in source.RequiredHttpHeaders)
{
options.RequestHeaders[header.Key] = header.Value;
@@ -1495,8 +1483,6 @@ namespace MediaBrowser.Server.Implementations.Channels
};
}
- IncrementDownloadCount(host, limit);
-
if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase) && response.ContentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
{
var extension = response.ContentType.Split('/')
@@ -1531,46 +1517,5 @@ namespace MediaBrowser.Server.Implementations.Channels
}
}
-
- private void IncrementDownloadCount(string key, int? limit)
- {
- if (!limit.HasValue)
- {
- return;
- }
-
- int current;
- _downloadCounts.TryGetValue(key, out current);
-
- current++;
- _downloadCounts.AddOrUpdate(key, current, (k, v) => current);
- }
-
- private bool ValidateDownloadLimit(string key, int? limit)
- {
- if (!limit.HasValue)
- {
- return true;
- }
-
- int current;
- _downloadCounts.TryGetValue(key, out current);
-
- return current < limit.Value;
- }
-
- public void Dispose()
- {
- if (_clearDownloadCountsTimer != null)
- {
- _clearDownloadCountsTimer.Dispose();
- _clearDownloadCountsTimer = null;
- }
- if (_refreshTimer != null)
- {
- _refreshTimer.Dispose();
- _refreshTimer = null;
- }
- }
}
}
diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
index a7d3854e7..d7df37332 100644
--- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
+++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
@@ -121,20 +121,12 @@ namespace MediaBrowser.Server.Implementations.Configuration
((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = metadataPath;
- if (Configuration.MergeMetadataAndImagesByName)
- {
- ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath;
- }
+ ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath;
}
private string GetInternalMetadataPath()
{
- if (Configuration.EnableStandaloneMetadata)
- {
- return Path.Combine(ApplicationPaths.ProgramDataPath, "metadata");
- }
-
- return null;
+ return Path.Combine(ApplicationPaths.ProgramDataPath, "metadata");
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
index 6dab136a5..12de5f6ef 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
@@ -13,12 +13,13 @@ using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Threading;
namespace MediaBrowser.Server.Implementations.Connect
{
public class ConnectEntryPoint : IServerEntryPoint
{
- private Timer _timer;
+ private PeriodicTimer _timer;
private readonly IHttpClient _httpClient;
private readonly IApplicationPaths _appPaths;
private readonly ILogger _logger;
@@ -43,7 +44,7 @@ namespace MediaBrowser.Server.Implementations.Connect
{
Task.Run(() => LoadCachedAddress());
- _timer = new Timer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(3));
+ _timer = new PeriodicTimer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(3));
}
private readonly string[] _ipLookups = { "http://bot.whatismyipaddress.com", "https://connect.emby.media/service/ip" };
diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs b/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs
index 43b1e693c..9e4a45253 100644
--- a/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs
+++ b/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs
@@ -25,7 +25,7 @@ namespace MediaBrowser.Server.Implementations.Devices
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
- private ConcurrentBag<DeviceInfo> _devices;
+ private List<DeviceInfo> _devices;
public DeviceRepository(IApplicationPaths appPaths, IJsonSerializer json, ILogger logger, IFileSystem fileSystem)
{
@@ -93,17 +93,14 @@ namespace MediaBrowser.Server.Implementations.Devices
public IEnumerable<DeviceInfo> GetDevices()
{
- if (_devices == null)
+ lock (_syncLock)
{
- lock (_syncLock)
+ if (_devices == null)
{
- if (_devices == null)
- {
- _devices = new ConcurrentBag<DeviceInfo>(LoadDevices());
- }
+ _devices = LoadDevices().ToList();
}
+ return _devices.ToList();
}
- return _devices.ToList();
}
private IEnumerable<DeviceInfo> LoadDevices()
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
index a2ffa9aff..2b2c338dd 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
@@ -11,6 +11,7 @@ using System.IO;
using System.Net;
using System.Text;
using System.Threading;
+using MediaBrowser.Common.Threading;
namespace MediaBrowser.Server.Implementations.EntryPoints
{
@@ -21,7 +22,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private readonly IServerConfigurationManager _config;
private readonly ISsdpHandler _ssdp;
- private Timer _timer;
+ private PeriodicTimer _timer;
private bool _isStarted;
public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp)
@@ -95,7 +96,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
NatUtility.UnhandledException += NatUtility_UnhandledException;
NatUtility.StartDiscovery();
- _timer = new Timer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
+ _timer = new PeriodicTimer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
_ssdp.MessageReceived += _ssdp_MessageReceived;
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs
index 701cf21fb..efda36821 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Model.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.Threading;
namespace MediaBrowser.Server.Implementations.EntryPoints
{
@@ -22,7 +23,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// </summary>
private readonly ILogger _logger;
- private Timer _timer;
+ private PeriodicTimer _timer;
/// <summary>
/// Initializes a new instance of the <see cref="LoadRegistrations" /> class.
@@ -41,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// </summary>
public void Run()
{
- _timer = new Timer(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(12));
+ _timer = new PeriodicTimer(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(12));
}
private async Task LoadAllRegistrations()
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
index c3b9c0d4d..d8aef909b 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
@@ -9,6 +9,7 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
+using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.EntryPoints
{
@@ -23,7 +24,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private readonly ISessionManager _sessionManager;
private readonly IUserManager _userManager;
- private Timer _timer;
private readonly TimeSpan _frequency = TimeSpan.FromHours(24);
private readonly ConcurrentDictionary<Guid, ClientInfo> _apps = new ConcurrentDictionary<Guid, ClientInfo>();
@@ -95,16 +95,16 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
return info;
}
- public void Run()
+ public async void Run()
{
- _timer = new Timer(OnTimerFired, null, TimeSpan.FromMilliseconds(5000), _frequency);
+ await Task.Delay(5000).ConfigureAwait(false);
+ OnTimerFired();
}
/// <summary>
/// Called when [timer fired].
/// </summary>
- /// <param name="state">The state.</param>
- private async void OnTimerFired(object state)
+ private async void OnTimerFired()
{
try
{
@@ -121,12 +121,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
public void Dispose()
{
_sessionManager.SessionStarted -= _sessionManager_SessionStarted;
-
- if (_timer != null)
- {
- _timer.Dispose();
- _timer = null;
- }
}
}
}
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
index 26392f5a9..73cc5ab01 100644
--- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
+++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
@@ -76,50 +76,50 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
var seasonNumber = episodeInfo.SeasonNumber;
- result.ExtractedSeasonNumber = seasonNumber;
-
- // Passing in true will include a few extra regex's
- var episodeNumber = episodeInfo.EpisodeNumber;
-
- result.ExtractedEpisodeNumber = episodeNumber;
-
- var premiereDate = episodeInfo.IsByDate ?
- new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value) :
- (DateTime?)null;
-
- if (episodeInfo.IsByDate || (seasonNumber.HasValue && episodeNumber.HasValue))
- {
- if (episodeInfo.IsByDate)
- {
- _logger.Debug("Extracted information from {0}. Series name {1}, Date {2}", path, seriesName, premiereDate.Value);
- }
- else
- {
- _logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, seasonNumber, episodeNumber);
- }
-
- var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber;
-
- result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
-
- await OrganizeEpisode(path,
- seriesName,
- seasonNumber,
- episodeNumber,
- endingEpisodeNumber,
- premiereDate,
- options,
- overwriteExisting,
- result,
- cancellationToken).ConfigureAwait(false);
- }
- else
- {
- var msg = string.Format("Unable to determine episode number from {0}", path);
- result.Status = FileSortingStatus.Failure;
- result.StatusMessage = msg;
- _logger.Warn(msg);
- }
+ result.ExtractedSeasonNumber = seasonNumber;
+
+ // Passing in true will include a few extra regex's
+ var episodeNumber = episodeInfo.EpisodeNumber;
+
+ result.ExtractedEpisodeNumber = episodeNumber;
+
+ var premiereDate = episodeInfo.IsByDate ?
+ new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value) :
+ (DateTime?)null;
+
+ if (episodeInfo.IsByDate || (seasonNumber.HasValue && episodeNumber.HasValue))
+ {
+ if (episodeInfo.IsByDate)
+ {
+ _logger.Debug("Extracted information from {0}. Series name {1}, Date {2}", path, seriesName, premiereDate.Value);
+ }
+ else
+ {
+ _logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, seasonNumber, episodeNumber);
+ }
+
+ var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber;
+
+ result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
+
+ await OrganizeEpisode(path,
+ seriesName,
+ seasonNumber,
+ episodeNumber,
+ endingEpisodeNumber,
+ premiereDate,
+ options,
+ overwriteExisting,
+ result,
+ cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ var msg = string.Format("Unable to determine episode number from {0}", path);
+ result.Status = FileSortingStatus.Failure;
+ result.StatusMessage = msg;
+ _logger.Warn(msg);
+ }
}
else
{
@@ -151,32 +151,32 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId));
- await OrganizeEpisode(result.OriginalPath,
- series,
- request.SeasonNumber,
- request.EpisodeNumber,
- request.EndingEpisodeNumber,
- null,
- options,
- true,
- result,
- cancellationToken).ConfigureAwait(false);
+ await OrganizeEpisode(result.OriginalPath,
+ series,
+ request.SeasonNumber,
+ request.EpisodeNumber,
+ request.EndingEpisodeNumber,
+ null,
+ options,
+ true,
+ result,
+ cancellationToken).ConfigureAwait(false);
await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
return result;
}
- private Task OrganizeEpisode(string sourcePath,
- string seriesName,
- int? seasonNumber,
- int? episodeNumber,
- int? endingEpiosdeNumber,
- DateTime? premiereDate,
- TvFileOrganizationOptions options,
- bool overwriteExisting,
- FileOrganizationResult result,
- CancellationToken cancellationToken)
+ private Task OrganizeEpisode(string sourcePath,
+ string seriesName,
+ int? seasonNumber,
+ int? episodeNumber,
+ int? endingEpiosdeNumber,
+ DateTime? premiereDate,
+ TvFileOrganizationOptions options,
+ bool overwriteExisting,
+ FileOrganizationResult result,
+ CancellationToken cancellationToken)
{
var series = GetMatchingSeries(seriesName, result);
@@ -189,33 +189,33 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
return Task.FromResult(true);
}
- return OrganizeEpisode(sourcePath,
- series,
- seasonNumber,
- episodeNumber,
- endingEpiosdeNumber,
- premiereDate,
- options,
- overwriteExisting,
- result,
- cancellationToken);
+ return OrganizeEpisode(sourcePath,
+ series,
+ seasonNumber,
+ episodeNumber,
+ endingEpiosdeNumber,
+ premiereDate,
+ options,
+ overwriteExisting,
+ result,
+ cancellationToken);
}
- private async Task OrganizeEpisode(string sourcePath,
- Series series,
- int? seasonNumber,
- int? episodeNumber,
- int? endingEpiosdeNumber,
- DateTime? premiereDate,
- TvFileOrganizationOptions options,
- bool overwriteExisting,
- FileOrganizationResult result,
- CancellationToken cancellationToken)
+ private async Task OrganizeEpisode(string sourcePath,
+ Series series,
+ int? seasonNumber,
+ int? episodeNumber,
+ int? endingEpiosdeNumber,
+ DateTime? premiereDate,
+ TvFileOrganizationOptions options,
+ bool overwriteExisting,
+ FileOrganizationResult result,
+ CancellationToken cancellationToken)
{
_logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path);
// Proceed to sort the file
- var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options, cancellationToken).ConfigureAwait(false);
+ var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options, cancellationToken).ConfigureAwait(false);
if (string.IsNullOrEmpty(newPath))
{
@@ -324,17 +324,17 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
}
}
- private List<string> GetOtherDuplicatePaths(string targetPath,
- Series series,
- int? seasonNumber,
- int? episodeNumber,
- int? endingEpisodeNumber)
+ private List<string> GetOtherDuplicatePaths(string targetPath,
+ Series series,
+ int? seasonNumber,
+ int? episodeNumber,
+ int? endingEpisodeNumber)
{
- // TODO: Support date-naming?
- if (!seasonNumber.HasValue || episodeNumber.HasValue)
- {
- return new List<string> ();
- }
+ // TODO: Support date-naming?
+ if (!seasonNumber.HasValue || episodeNumber.HasValue)
+ {
+ return new List<string>();
+ }
var episodePaths = series.GetRecursiveChildren()
.OfType<Episode>()
@@ -462,16 +462,18 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
/// <param name="seasonNumber">The season number.</param>
/// <param name="episodeNumber">The episode number.</param>
/// <param name="endingEpisodeNumber">The ending episode number.</param>
+ /// <param name="premiereDate">The premiere date.</param>
/// <param name="options">The options.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>System.String.</returns>
- private async Task<string> GetNewPath(string sourcePath,
- Series series,
- int? seasonNumber,
- int? episodeNumber,
- int? endingEpisodeNumber,
- DateTime? premiereDate,
- TvFileOrganizationOptions options,
- CancellationToken cancellationToken)
+ private async Task<string> GetNewPath(string sourcePath,
+ Series series,
+ int? seasonNumber,
+ int? episodeNumber,
+ int? endingEpisodeNumber,
+ DateTime? premiereDate,
+ TvFileOrganizationOptions options,
+ CancellationToken cancellationToken)
{
var episodeInfo = new EpisodeInfo
{
@@ -481,7 +483,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
MetadataLanguage = series.GetPreferredMetadataLanguage(),
ParentIndexNumber = seasonNumber,
SeriesProviderIds = series.ProviderIds,
- PremiereDate = premiereDate
+ PremiereDate = premiereDate
};
var searchResults = await _providerManager.GetRemoteSearchResults<Episode, EpisodeInfo>(new RemoteSearchQuery<EpisodeInfo>
@@ -491,22 +493,25 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
}, cancellationToken).ConfigureAwait(false);
var episode = searchResults.FirstOrDefault();
-
- string episodeName = string.Empty;
if (episode == null)
{
var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber);
_logger.Warn(msg);
- //throw new Exception(msg);
+ return null;
}
- else
- {
- episodeName = episode.Name;
- }
- seasonNumber = seasonNumber ?? episode.ParentIndexNumber;
- episodeNumber = episodeNumber ?? episode.IndexNumber;
+ var episodeName = episode.Name;
+
+ //if (string.IsNullOrWhiteSpace(episodeName))
+ //{
+ // var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber);
+ // _logger.Warn(msg);
+ // return null;
+ //}
+
+ seasonNumber = seasonNumber ?? episode.ParentIndexNumber;
+ episodeNumber = episodeNumber ?? episode.IndexNumber;
var newPath = GetSeasonFolderPath(series, seasonNumber.Value, options);
@@ -579,7 +584,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
seriesName = _fileSystem.GetValidFilename(seriesName).Trim();
- if (string.IsNullOrEmpty(episodeTitle))
+ if (string.IsNullOrWhiteSpace(episodeTitle))
{
episodeTitle = string.Empty;
}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
index 6a23a8497..038116703 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -256,6 +256,25 @@ namespace MediaBrowser.Server.Implementations.HttpServer
}
}
+ private readonly Dictionary<string, int> _skipLogExtensions = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
+ {
+ {".js", 0},
+ {".css", 0},
+ {".woff", 0},
+ {".woff2", 0},
+ {".ttf", 0},
+ {".html", 0}
+ };
+
+ private bool EnableLogging(string url)
+ {
+ var parts = url.Split(new[] { '?' }, 2);
+
+ var extension = Path.GetExtension(parts[0]);
+
+ return string.IsNullOrWhiteSpace(extension) || !_skipLogExtensions.ContainsKey(extension);
+ }
+
/// <summary>
/// Overridable method that can be used to implement a custom hnandler
/// </summary>
@@ -271,6 +290,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer
var operationName = httpReq.OperationName;
var localPath = url.LocalPath;
+ var urlString = url.OriginalString;
+ var enableLog = EnableLogging(urlString);
+
+ if (enableLog)
+ {
+ LoggerUtils.LogRequest(_logger, urlString, httpReq.HttpMethod, httpReq.UserAgent);
+ }
+
if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) ||
string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase))
{
@@ -333,15 +360,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
task.ContinueWith(x => httpRes.Close(), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent);
//Matches Exceptions handled in HttpListenerBase.InitTask()
- var urlString = url.ToString();
-
task.ContinueWith(x =>
{
var statusCode = httpRes.StatusCode;
var duration = DateTime.Now - date;
- LoggerUtils.LogResponse(_logger, statusCode, urlString, remoteIp, duration);
+ if (enableLog)
+ {
+ LoggerUtils.LogResponse(_logger, statusCode, urlString, remoteIp, duration);
+ }
}, TaskContinuationOptions.None);
return task;
diff --git a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs
index fae702023..0b8caaa6e 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs
@@ -1,12 +1,31 @@
using MediaBrowser.Model.Logging;
using System;
using System.Globalization;
+using System.IO;
+using SocketHttpListener.Net;
namespace MediaBrowser.Server.Implementations.HttpServer
{
public static class LoggerUtils
{
/// <summary>
+ /// Logs the request.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="request">The request.</param>
+ public static void LogRequest(ILogger logger, HttpListenerRequest request)
+ {
+ var url = request.Url.ToString();
+
+ logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), url, request.UserAgent ?? string.Empty);
+ }
+
+ public static void LogRequest(ILogger logger, string url, string method, string userAgent)
+ {
+ logger.Info("{0} {1}. UserAgent: {2}", ("HTTP " + method), url, userAgent ?? string.Empty);
+ }
+
+ /// <summary>
/// Logs the response.
/// </summary>
/// <param name="logger">The logger.</param>
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
index a91b1e3ed..a029e0955 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
@@ -78,10 +78,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{
var request = context.Request;
- LogRequest(_logger, request);
-
if (request.IsWebSocketRequest)
{
+ LoggerUtils.LogRequest(_logger, request);
+
ProcessWebSocketRequest(context);
return Task.FromResult(true);
}
@@ -156,44 +156,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
return req;
}
- /// <summary>
- /// Logs the request.
- /// </summary>
- /// <param name="logger">The logger.</param>
- /// <param name="request">The request.</param>
- private static void LogRequest(ILogger logger, HttpListenerRequest request)
- {
- var url = request.Url.ToString();
- var extension = Path.GetExtension(url);
-
- if (string.Equals(extension, ".js", StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
- if (string.Equals(extension, ".css", StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
- if (string.Equals(extension, ".woff", StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
- if (string.Equals(extension, ".woff2", StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
- if (string.Equals(extension, ".ttf", StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
- if (string.Equals(extension, ".html", StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
-
- logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), url, request.UserAgent ?? string.Empty);
- }
-
private void HandleError(Exception ex, HttpListenerContext context)
{
var httpReq = GetRequest(context);
diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
index 85ea8ec57..184b72d8f 100644
--- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
+++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
@@ -471,11 +471,11 @@ namespace MediaBrowser.Server.Implementations.IO
{
if (_updateTimer == null)
{
- _updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeLibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
+ _updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
}
else
{
- _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeLibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
+ _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
}
}
}
@@ -513,12 +513,18 @@ namespace MediaBrowser.Server.Implementations.IO
private bool IsFileLocked(string path)
{
+ if (Environment.OSVersion.Platform != PlatformID.Win32NT)
+ {
+ // Causing lockups on linux
+ return false;
+ }
+
try
{
var data = _fileSystem.GetFileSystemInfo(path);
if (!data.Exists
- || data.Attributes.HasFlag(FileAttributes.Directory)
+ || data.IsDirectory
// Opening a writable stream will fail with readonly files
|| data.Attributes.HasFlag(FileAttributes.ReadOnly))
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index 0cb5174c9..b0b2680ca 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -222,7 +222,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <summary>
/// The _root folder
/// </summary>
- private AggregateFolder _rootFolder;
+ private volatile AggregateFolder _rootFolder;
/// <summary>
/// The _root folder sync lock
/// </summary>
@@ -743,7 +743,7 @@ namespace MediaBrowser.Server.Implementations.Library
return rootFolder;
}
- private UserRootFolder _userRootFolder;
+ private volatile UserRootFolder _userRootFolder;
private readonly object _syncLock = new object();
public Folder GetUserRootFolder()
{
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
index 407aac53d..8beb03b71 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
@@ -51,8 +51,17 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
{
var filename = Path.GetFileNameWithoutExtension(path) ?? string.Empty;
- return !IgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase)
- && imageProcessor.SupportedInputFormats.Contains((Path.GetExtension(path) ?? string.Empty).TrimStart('.'), StringComparer.OrdinalIgnoreCase);
+ if (IgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+
+ if (IgnoreFiles.Any(i => filename.IndexOf("-" + i, StringComparison.OrdinalIgnoreCase) != -1))
+ {
+ return false;
+ }
+
+ return imageProcessor.SupportedInputFormats.Contains((Path.GetExtension(path) ?? string.Empty).TrimStart('.'), StringComparer.OrdinalIgnoreCase);
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
index 30a720a62..0df4742bd 100644
--- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
@@ -163,7 +163,14 @@ namespace MediaBrowser.Server.Implementations.Library
var channels = channelResult.Items;
- list.AddRange(channels);
+ if (user.Configuration.DisplayChannelsInline && channels.Length > 0)
+ {
+ list.Add(await _channelManager.GetInternalChannelFolder(cancellationToken).ConfigureAwait(false));
+ }
+ else
+ {
+ list.AddRange(channels);
+ }
if (_liveTvManager.GetEnabledUsers().Select(i => i.Id.ToString("N")).Contains(query.UserId))
{
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 356d0d83d..cd91684ce 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -22,12 +22,15 @@ using MediaBrowser.Server.Implementations.FileOrganization;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Power;
+using Microsoft.Win32;
namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
@@ -55,7 +58,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public static EmbyTV Current;
- public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ISecurityManager security, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder)
+ public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ISecurityManager security, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder, IPowerManagement powerManagement)
{
Current = this;
@@ -75,13 +78,26 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_recordingProvider = new ItemDataProvider<RecordingInfo>(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "recordings"), (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase));
_seriesTimerProvider = new SeriesTimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers"));
- _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"));
+ _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), powerManagement, _logger);
_timerProvider.TimerFired += _timerProvider_TimerFired;
}
public void Start()
{
_timerProvider.RestartTimers();
+
+ SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
+
+ }
+
+ void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
+ {
+ _logger.Info("Power mode changed to {0}", e.Mode);
+
+ if (e.Mode == PowerModes.Resume)
+ {
+ _timerProvider.RestartTimers();
+ }
}
public event EventHandler DataSourceChanged;
@@ -155,7 +171,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
epgData = GetEpgDataForChannel(timer.ChannelId);
}
- await UpdateTimersForSeriesTimer(epgData, timer).ConfigureAwait(false);
+ await UpdateTimersForSeriesTimer(epgData, timer, false).ConfigureAwait(false);
}
var timers = await GetTimersAsync(cancellationToken).ConfigureAwait(false);
@@ -223,7 +239,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken)
{
- var timers = _timerProvider.GetAll().Where(i => string.Equals(i.SeriesTimerId, timerId, StringComparison.OrdinalIgnoreCase));
+ var timers = _timerProvider
+ .GetAll()
+ .Where(i => string.Equals(i.SeriesTimerId, timerId, StringComparison.OrdinalIgnoreCase))
+ .ToList();
+
foreach (var timer in timers)
{
CancelTimerInternal(timer.Id);
@@ -332,25 +352,44 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
}
_seriesTimerProvider.Add(info);
- await UpdateTimersForSeriesTimer(epgData, info).ConfigureAwait(false);
+ await UpdateTimersForSeriesTimer(epgData, info, false).ConfigureAwait(false);
}
public async Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken)
{
- _seriesTimerProvider.Update(info);
- List<ProgramInfo> epgData;
- if (info.RecordAnyChannel)
- {
- var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false);
- var channelIds = channels.Select(i => i.Id).ToList();
- epgData = GetEpgDataForChannels(channelIds);
- }
- else
+ var instance = _seriesTimerProvider.GetAll().FirstOrDefault(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase));
+
+ if (instance != null)
{
- epgData = GetEpgDataForChannel(info.ChannelId);
- }
+ instance.ChannelId = info.ChannelId;
+ instance.Days = info.Days;
+ instance.EndDate = info.EndDate;
+ instance.IsPostPaddingRequired = info.IsPostPaddingRequired;
+ instance.IsPrePaddingRequired = info.IsPrePaddingRequired;
+ instance.PostPaddingSeconds = info.PostPaddingSeconds;
+ instance.PrePaddingSeconds = info.PrePaddingSeconds;
+ instance.Priority = info.Priority;
+ instance.RecordAnyChannel = info.RecordAnyChannel;
+ instance.RecordAnyTime = info.RecordAnyTime;
+ instance.RecordNewOnly = info.RecordNewOnly;
+ instance.StartDate = info.StartDate;
- await UpdateTimersForSeriesTimer(epgData, info).ConfigureAwait(false);
+ _seriesTimerProvider.Update(instance);
+
+ List<ProgramInfo> epgData;
+ if (instance.RecordAnyChannel)
+ {
+ var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false);
+ var channelIds = channels.Select(i => i.Id).ToList();
+ epgData = GetEpgDataForChannels(channelIds);
+ }
+ else
+ {
+ epgData = GetEpgDataForChannel(instance.ChannelId);
+ }
+
+ await UpdateTimersForSeriesTimer(epgData, instance, true).ConfigureAwait(false);
+ }
}
public Task UpdateTimerAsync(TimerInfo info, CancellationToken cancellationToken)
@@ -603,6 +642,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
await RecordStream(timer, recordingEndDate, cancellationTokenSource.Token).ConfigureAwait(false);
}
+ else
+ {
+ _logger.Info("Skipping RecordStream because it's already in progress.");
+ }
}
catch (OperationCanceledException)
{
@@ -721,7 +764,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
recording.DateLastUpdated = DateTime.UtcNow;
_recordingProvider.AddOrUpdate(recording);
- _logger.Info("Beginning recording.");
+ _logger.Info("Beginning recording. Will record for {0} minutes.", duration.TotalMinutes.ToString(CultureInfo.InvariantCulture));
httpRequestOptions.BufferContent = false;
var durationToken = new CancellationTokenSource(duration);
@@ -836,7 +879,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return _config.GetConfiguration<LiveTvOptions>("livetv");
}
- private async Task UpdateTimersForSeriesTimer(List<ProgramInfo> epgData, SeriesTimerInfo seriesTimer)
+ private async Task UpdateTimersForSeriesTimer(List<ProgramInfo> epgData, SeriesTimerInfo seriesTimer, bool deleteInvalidTimers)
{
var newTimers = GetTimersForSeries(seriesTimer, epgData, _recordingProvider.GetAll()).ToList();
@@ -849,12 +892,29 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
_timerProvider.AddOrUpdate(timer);
}
}
+
+ if (deleteInvalidTimers)
+ {
+ var allTimers = GetTimersForSeries(seriesTimer, epgData, new List<RecordingInfo>())
+ .Select(i => i.Id)
+ .ToList();
+
+ var deletes = _timerProvider.GetAll()
+ .Where(i => string.Equals(i.SeriesTimerId, seriesTimer.Id, StringComparison.OrdinalIgnoreCase))
+ .Where(i => !allTimers.Contains(i.Id, StringComparer.OrdinalIgnoreCase) && i.StartDate > DateTime.UtcNow)
+ .ToList();
+
+ foreach (var timer in deletes)
+ {
+ await CancelTimerAsync(timer.Id, CancellationToken.None).ConfigureAwait(false);
+ }
+ }
}
private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer, IEnumerable<ProgramInfo> allPrograms, IReadOnlyList<RecordingInfo> currentRecordings)
{
// Exclude programs that have already ended
- allPrograms = allPrograms.Where(i => i.EndDate > DateTime.UtcNow);
+ allPrograms = allPrograms.Where(i => i.EndDate > DateTime.UtcNow && i.StartDate > DateTime.UtcNow);
allPrograms = GetProgramsForSeries(seriesTimer, allPrograms);
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
index f46daa6d5..b29a7562c 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
@@ -13,7 +13,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
where T : class
{
private readonly object _fileDataLock = new object();
- private List<T> _items;
+ private volatile List<T> _items;
private readonly IJsonSerializer _jsonSerializer;
protected readonly ILogger Logger;
private readonly string _dataPath;
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
index 80bb671fa..5d462f106 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
@@ -5,22 +5,27 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Concurrent;
+using System.Globalization;
using System.Linq;
using System.Threading;
using CommonIO;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Power;
namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
public class TimerManager : ItemDataProvider<TimerInfo>
{
private readonly ConcurrentDictionary<string, Timer> _timers = new ConcurrentDictionary<string, Timer>(StringComparer.OrdinalIgnoreCase);
+ private readonly IPowerManagement _powerManagement;
+ private readonly ILogger _logger;
public event EventHandler<GenericEventArgs<TimerInfo>> TimerFired;
- public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath)
+ public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, IPowerManagement powerManagement, ILogger logger1)
: base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase))
{
+ _powerManagement = powerManagement;
+ _logger = logger1;
}
public void RestartTimers()
@@ -58,6 +63,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
var timespan = RecordingHelper.GetStartTime(item) - DateTime.UtcNow;
timer.Change(timespan, TimeSpan.Zero);
+ ScheduleWake(item);
}
else
{
@@ -74,6 +80,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
base.Add(item);
AddTimer(item);
+ ScheduleWake(item);
}
private void AddTimer(TimerInfo item)
@@ -91,15 +98,39 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
StartTimer(item, timerLength);
}
+ private void ScheduleWake(TimerInfo info)
+ {
+ var startDate = RecordingHelper.GetStartTime(info).AddMinutes(-5);
+
+ try
+ {
+ _powerManagement.ScheduleWake(startDate);
+ _logger.Info("Scheduled system wake timer at {0} (UTC)", startDate);
+ }
+ catch (NotImplementedException)
+ {
+
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error scheduling wake timer", ex);
+ }
+ }
+
public void StartTimer(TimerInfo item, TimeSpan length)
{
StopTimer(item);
var timer = new Timer(TimerCallback, item.Id, length, TimeSpan.Zero);
- if (!_timers.TryAdd(item.Id, timer))
+ if (_timers.TryAdd(item.Id, timer))
+ {
+ _logger.Info("Creating recording timer for {0}, {1}. Timer will fire in {2} minutes", item.Id, item.Name, length.TotalMinutes.ToString(CultureInfo.InvariantCulture));
+ }
+ else
{
timer.Dispose();
+ _logger.Warn("Timer already exists for item {0}", item.Id);
}
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index e09e06bd4..8bf1d27b8 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -1954,6 +1954,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
await service.CreateTimerAsync(info, cancellationToken).ConfigureAwait(false);
_lastRecordingRefreshTime = DateTime.MinValue;
+ _logger.Info("New recording scheduled");
}
public async Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ca.json b/MediaBrowser.Server.Implementations/Localization/Core/ca.json
index 40dfcd2c3..83d72030f 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/ca.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/ca.json
@@ -1,6 +1,6 @@
{
- "AppDeviceValues": "App: {0}, Device: {1}",
- "UserDownloadingItemWithValues": "{0} is downloading {1}",
+ "AppDeviceValues": "App: {0}, Dispositiu: {1}",
+ "UserDownloadingItemWithValues": "{0} est\u00e0 descarregant {1}",
"FolderTypeMixed": "Mixed content",
"FolderTypeMovies": "Pel\u00b7l\u00edcules",
"FolderTypeMusic": "M\u00fasica",
@@ -12,10 +12,10 @@
"FolderTypeBooks": "Llibres",
"FolderTypeTvShows": "TV",
"FolderTypeInherit": "Heretat",
- "HeaderCastCrew": "Repartiment i equip",
+ "HeaderCastCrew": "Repartiment i Equip",
"HeaderPeople": "People",
"ValueSpecialEpisodeName": "Special - {0}",
- "LabelChapterName": "Chapter {0}",
+ "LabelChapterName": "Cap\u00edtol {0}",
"NameSeasonNumber": "Temporada {0}",
"LabelExit": "Sortir",
"LabelVisitCommunity": "Visita la comunitat",
@@ -77,7 +77,7 @@
"ViewTypeMovieMovies": "Pel\u00b7l\u00edcules",
"ViewTypeMovieCollections": "Col\u00b7leccions",
"ViewTypeMovieFavorites": "Preferides",
- "ViewTypeMovieGenres": "Genres",
+ "ViewTypeMovieGenres": "G\u00e8neres",
"ViewTypeMusicLatest": "Novetats",
"ViewTypeMusicPlaylists": "Llistes de reproducci\u00f3",
"ViewTypeMusicAlbums": "\u00c0lbums",
@@ -89,7 +89,7 @@
"ViewTypeMusicFavoriteArtists": "Artistes Preferits",
"ViewTypeMusicFavoriteSongs": "Can\u00e7ons Preferides",
"ViewTypeFolders": "Directoris",
- "ViewTypeLiveTvRecordingGroups": "Recordings",
+ "ViewTypeLiveTvRecordingGroups": "Enregistraments",
"ViewTypeLiveTvChannels": "Canals",
"ScheduledTaskFailedWithName": "{0} failed",
"LabelRunningTimeValue": "Running time: {0}",
@@ -103,7 +103,7 @@
"LabelIpAddressValue": "Ip address: {0}",
"DeviceOnlineWithName": "{0} is connected",
"UserOnlineFromDevice": "{0} is online from {1}",
- "ProviderValue": "Provider: {0}",
+ "ProviderValue": "Prove\u00efdor: {0}",
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
"UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
"UserCreatedWithName": "User {0} has been created",
@@ -113,12 +113,12 @@
"MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
"MessageApplicationUpdated": "Emby Server has been updated",
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
- "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "AuthenticationSucceededWithUserName": "{0} autenticat correctament",
"DeviceOfflineWithName": "{0} has disconnected",
"UserLockedOutWithName": "User {0} has been locked out",
"UserOfflineFromDevice": "{0} has disconnected from {1}",
- "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
- "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "UserStartedPlayingItemWithValues": "{0} ha comen\u00e7at a reproduir {1}",
+ "UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"HeaderUnidentified": "Unidentified",
"HeaderImagePrimary": "Primary",
@@ -164,7 +164,7 @@
"HeaderTracks": "Tracks",
"HeaderMusicArtist": "M\u00fasic",
"HeaderLocked": "Locked",
- "HeaderStudios": "Studios",
+ "HeaderStudios": "Estudis",
"HeaderActor": "Actors",
"HeaderComposer": "Compositors",
"HeaderDirector": "Directors",
diff --git a/MediaBrowser.Server.Implementations/Localization/Core/nl.json b/MediaBrowser.Server.Implementations/Localization/Core/nl.json
index b32ebefc3..fd0c586a2 100644
--- a/MediaBrowser.Server.Implementations/Localization/Core/nl.json
+++ b/MediaBrowser.Server.Implementations/Localization/Core/nl.json
@@ -63,7 +63,7 @@
"ViewTypeLatestGames": "Nieuwste games",
"ViewTypeRecentlyPlayedGames": "Recent gespeelt",
"ViewTypeGameFavorites": "Favorieten",
- "ViewTypeGameSystems": "Gam systemen",
+ "ViewTypeGameSystems": "Game systemen",
"ViewTypeGameGenres": "Genres",
"ViewTypeTvResume": "Hervatten",
"ViewTypeTvNextUp": "Volgende",
@@ -147,7 +147,7 @@
"HeaderCommunityRating": "Gemeenschap cijfer",
"HeaderTrailers": "Trailers",
"HeaderSpecials": "Specials",
- "HeaderGameSystems": "Spel systemen",
+ "HeaderGameSystems": "Game systemen",
"HeaderPlayers": "Spelers:",
"HeaderAlbumArtists": "Album artiesten",
"HeaderAlbums": "Albums",
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index e5c94a01b..c54ea42a5 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -48,9 +48,9 @@
<Reference Include="Interfaces.IO">
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
</Reference>
- <Reference Include="MediaBrowser.Naming, Version=1.0.5818.23111, Culture=neutral, processorArchitecture=MSIL">
+ <Reference Include="MediaBrowser.Naming, Version=1.0.5869.26812, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\MediaBrowser.Naming.1.0.0.41\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
+ <HintPath>..\packages\MediaBrowser.Naming.1.0.0.44\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
</Reference>
<Reference Include="MoreLinq">
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
diff --git a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs b/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs
index e8f910f81..969541fbc 100644
--- a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs
@@ -1,6 +1,5 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Notifications;
@@ -17,12 +16,13 @@ using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using CommonIO;
+using MediaBrowser.Common.Threading;
namespace MediaBrowser.Server.Implementations.News
{
public class NewsEntryPoint : IServerEntryPoint
{
- private Timer _timer;
+ private PeriodicTimer _timer;
private readonly IHttpClient _httpClient;
private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
@@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.News
public void Run()
{
- _timer = new Timer(OnTimerFired, null, TimeSpan.FromMilliseconds(500), _frequency);
+ _timer = new PeriodicTimer(OnTimerFired, null, TimeSpan.FromMilliseconds(500), _frequency);
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index 5c04f2782..b7f5533ce 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -2,7 +2,7 @@
<packages>
<package id="CommonIO" version="1.0.0.7" targetFramework="net45" />
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
- <package id="MediaBrowser.Naming" version="1.0.0.41" targetFramework="net45" />
+ <package id="MediaBrowser.Naming" version="1.0.0.44" targetFramework="net45" />
<package id="Mono.Nat" version="1.2.24.0" targetFramework="net45" />
<package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />