update recording layouts

This commit is contained in:
Luke Pulverenti 2016-09-26 14:59:18 -04:00
parent 2d00811450
commit adb39f4090
8 changed files with 200 additions and 62 deletions

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Controller.LiveTv namespace MediaBrowser.Controller.LiveTv
{ {
@ -54,6 +55,7 @@ namespace MediaBrowser.Controller.LiveTv
public bool RecordAnyChannel { get; set; } public bool RecordAnyChannel { get; set; }
public int KeepUpTo { get; set; } public int KeepUpTo { get; set; }
public KeepUntil KeepUntil { get; set; }
public bool SkipEpisodesInLibrary { get; set; } public bool SkipEpisodesInLibrary { get; set; }
@ -109,6 +111,7 @@ namespace MediaBrowser.Controller.LiveTv
{ {
Days = new List<DayOfWeek>(); Days = new List<DayOfWeek>();
SkipEpisodesInLibrary = true; SkipEpisodesInLibrary = true;
KeepUntil = KeepUntil.UntilDeleted;
} }
} }
} }

View file

@ -27,6 +27,7 @@ namespace MediaBrowser.Model.LiveTv
public bool RecordAnyChannel { get; set; } public bool RecordAnyChannel { get; set; }
public int KeepUpTo { get; set; } public int KeepUpTo { get; set; }
public KeepUntil KeepUntil { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether [record new only]. /// Gets or sets a value indicating whether [record new only].
@ -68,4 +69,12 @@ namespace MediaBrowser.Model.LiveTv
Days = new List<DayOfWeek>(); Days = new List<DayOfWeek>();
} }
} }
public enum KeepUntil
{
UntilDeleted,
UntilSpaceNeeded,
UntilWatched,
UntilDate
}
} }

View file

@ -117,7 +117,7 @@ namespace MediaBrowser.Providers.MediaInfo
{ {
get get
{ {
return new[] { ".srt", ".ssa", ".ass", ".sub" }; return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami" };
} }
} }

View file

@ -330,11 +330,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{ {
if (DateTime.UtcNow > timer.EndDate && !_activeRecordings.ContainsKey(timer.Id)) if (DateTime.UtcNow > timer.EndDate && !_activeRecordings.ContainsKey(timer.Id))
{ {
_timerProvider.Delete(timer); OnTimerOutOfDate(timer);
} }
} }
} }
private void OnTimerOutOfDate(TimerInfo timer)
{
_timerProvider.Delete(timer);
}
private List<ChannelInfo> _channelCache = null; private List<ChannelInfo> _channelCache = null;
private async Task<IEnumerable<ChannelInfo>> GetChannelsAsync(bool enableCache, CancellationToken cancellationToken) private async Task<IEnumerable<ChannelInfo>> GetChannelsAsync(bool enableCache, CancellationToken cancellationToken)
{ {
@ -424,7 +429,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
foreach (var timer in timers) foreach (var timer in timers)
{ {
CancelTimerInternal(timer.Id); CancelTimerInternal(timer.Id, true);
} }
var remove = _seriesTimerProvider.GetAll().FirstOrDefault(r => string.Equals(r.Id, timerId, StringComparison.OrdinalIgnoreCase)); var remove = _seriesTimerProvider.GetAll().FirstOrDefault(r => string.Equals(r.Id, timerId, StringComparison.OrdinalIgnoreCase));
@ -435,12 +440,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return Task.FromResult(true); return Task.FromResult(true);
} }
private void CancelTimerInternal(string timerId) private void CancelTimerInternal(string timerId, bool isSeriesCancelled)
{ {
var remove = _timerProvider.GetAll().FirstOrDefault(r => string.Equals(r.Id, timerId, StringComparison.OrdinalIgnoreCase)); var timer = _timerProvider.GetAll().FirstOrDefault(r => string.Equals(r.Id, timerId, StringComparison.OrdinalIgnoreCase));
if (remove != null) if (timer != null)
{ {
_timerProvider.Delete(remove); if (string.IsNullOrWhiteSpace(timer.SeriesTimerId) || isSeriesCancelled)
{
_timerProvider.Delete(timer);
}
else
{
timer.Status = RecordingStatus.Cancelled;
_timerProvider.AddOrUpdate(timer, false);
}
} }
ActiveRecordingInfo activeRecordingInfo; ActiveRecordingInfo activeRecordingInfo;
@ -452,7 +465,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public Task CancelTimerAsync(string timerId, CancellationToken cancellationToken) public Task CancelTimerAsync(string timerId, CancellationToken cancellationToken)
{ {
CancelTimerInternal(timerId); CancelTimerInternal(timerId, false);
return Task.FromResult(true); return Task.FromResult(true);
} }
@ -463,6 +476,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken) public Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken)
{ {
var existingTimer = _timerProvider.GetAll()
.FirstOrDefault(i => string.Equals(info.ProgramId, i.ProgramId, StringComparison.OrdinalIgnoreCase));
if (existingTimer != null)
{
if (existingTimer.Status == RecordingStatus.Cancelled)
{
existingTimer.Status = RecordingStatus.New;
_timerProvider.Update(existingTimer);
}
else
{
throw new ArgumentException("A scheduled recording already exists for this program.");
}
}
return CreateTimer(info, cancellationToken); return CreateTimer(info, cancellationToken);
} }
@ -549,6 +578,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
instance.RecordNewOnly = info.RecordNewOnly; instance.RecordNewOnly = info.RecordNewOnly;
instance.SkipEpisodesInLibrary = info.SkipEpisodesInLibrary; instance.SkipEpisodesInLibrary = info.SkipEpisodesInLibrary;
instance.KeepUpTo = info.KeepUpTo; instance.KeepUpTo = info.KeepUpTo;
instance.KeepUntil = info.KeepUntil;
instance.StartDate = info.StartDate; instance.StartDate = info.StartDate;
_seriesTimerProvider.Update(instance); _seriesTimerProvider.Update(instance);
@ -569,12 +599,54 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
} }
} }
public Task UpdateTimerAsync(TimerInfo info, CancellationToken cancellationToken) public Task UpdateTimerAsync(TimerInfo updatedTimer, CancellationToken cancellationToken)
{ {
_timerProvider.Update(info); var existingTimer = _timerProvider
.GetAll()
.FirstOrDefault(i => string.Equals(i.Id, updatedTimer.Id, StringComparison.OrdinalIgnoreCase));
if (existingTimer == null)
{
throw new ResourceNotFoundException();
}
// Only update if not currently active
ActiveRecordingInfo activeRecordingInfo;
if (!_activeRecordings.TryGetValue(updatedTimer.Id, out activeRecordingInfo))
{
UpdateExistingTimerWithNewData(existingTimer, updatedTimer);
_timerProvider.Update(existingTimer);
}
return Task.FromResult(true); return Task.FromResult(true);
} }
private void UpdateExistingTimerWithNewData(TimerInfo existingTimer, TimerInfo updatedTimer)
{
// Update the program info but retain the status
existingTimer.ChannelId = updatedTimer.ChannelId;
existingTimer.CommunityRating = updatedTimer.CommunityRating;
existingTimer.EndDate = updatedTimer.EndDate;
existingTimer.EpisodeNumber = updatedTimer.EpisodeNumber;
existingTimer.EpisodeTitle = updatedTimer.EpisodeTitle;
existingTimer.Genres = updatedTimer.Genres;
existingTimer.HomePageUrl = updatedTimer.HomePageUrl;
existingTimer.IsKids = updatedTimer.IsKids;
existingTimer.IsMovie = updatedTimer.IsMovie;
existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries;
existingTimer.IsSports = updatedTimer.IsSports;
existingTimer.Name = updatedTimer.Name;
existingTimer.OfficialRating = updatedTimer.OfficialRating;
existingTimer.OriginalAirDate = updatedTimer.OriginalAirDate;
existingTimer.Overview = updatedTimer.Overview;
existingTimer.ProductionYear = updatedTimer.ProductionYear;
existingTimer.ProgramId = updatedTimer.ProgramId;
existingTimer.SeasonNumber = updatedTimer.SeasonNumber;
existingTimer.ShortOverview = updatedTimer.ShortOverview;
existingTimer.StartDate = updatedTimer.StartDate;
}
public Task<ImageStream> GetChannelImageAsync(string channelId, CancellationToken cancellationToken) public Task<ImageStream> GetChannelImageAsync(string channelId, CancellationToken cancellationToken)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
@ -597,7 +669,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken) public Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken)
{ {
return Task.FromResult((IEnumerable<TimerInfo>)_timerProvider.GetAll()); var excludeStatues = new List<RecordingStatus>
{
RecordingStatus.Completed,
RecordingStatus.Cancelled
};
var timers = _timerProvider.GetAll()
.Where(i => !excludeStatues.Contains(i.Status));
return Task.FromResult(timers);
} }
public Task<SeriesTimerInfo> GetNewTimerDefaultsAsync(CancellationToken cancellationToken, ProgramInfo program = null) public Task<SeriesTimerInfo> GetNewTimerDefaultsAsync(CancellationToken cancellationToken, ProgramInfo program = null)
@ -630,6 +711,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
defaults.ProgramId = program.Id; defaults.ProgramId = program.Id;
} }
defaults.SkipEpisodesInLibrary = true;
defaults.KeepUntil = KeepUntil.UntilDeleted;
return Task.FromResult(defaults); return Task.FromResult(defaults);
} }
@ -860,8 +944,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
if (recordingEndDate <= DateTime.UtcNow) if (recordingEndDate <= DateTime.UtcNow)
{ {
_logger.Warn("Recording timer fired for timer {0}, Id: {1}, but the program has already ended.", timer.Name, timer.Id); _logger.Warn("Recording timer fired for updatedTimer {0}, Id: {1}, but the program has already ended.", timer.Name, timer.Id);
_timerProvider.Delete(timer); OnTimerOutOfDate(timer);
return; return;
} }
@ -982,7 +1066,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return Path.Combine(recordPath, recordingFileName); return Path.Combine(recordPath, recordingFileName);
} }
private async Task RecordStream(TimerInfo timer, DateTime recordingEndDate, ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken) private async Task RecordStream(TimerInfo timer, DateTime recordingEndDate,
ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken)
{ {
if (timer == null) if (timer == null)
{ {
@ -1014,9 +1099,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
try try
{ {
var allMediaSources = await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false); var allMediaSources =
await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false);
var liveStreamInfo = await GetChannelStreamInternal(timer.ChannelId, allMediaSources[0].Id, CancellationToken.None).ConfigureAwait(false); var liveStreamInfo =
await
GetChannelStreamInternal(timer.ChannelId, allMediaSources[0].Id, CancellationToken.None)
.ConfigureAwait(false);
liveStream = liveStreamInfo.Item1; liveStream = liveStreamInfo.Item1;
var mediaStreamInfo = liveStreamInfo.Item1.PublicMediaSource; var mediaStreamInfo = liveStreamInfo.Item1.PublicMediaSource;
var tunerHost = liveStreamInfo.Item2; var tunerHost = liveStreamInfo.Item2;
@ -1036,7 +1125,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
var duration = recordingEndDate - DateTime.UtcNow; var duration = recordingEndDate - DateTime.UtcNow;
_logger.Info("Beginning recording. Will record for {0} minutes.", duration.TotalMinutes.ToString(CultureInfo.InvariantCulture)); _logger.Info("Beginning recording. Will record for {0} minutes.",
duration.TotalMinutes.ToString(CultureInfo.InvariantCulture));
_logger.Info("Writing file to path: " + recordPath); _logger.Info("Writing file to path: " + recordPath);
_logger.Info("Opening recording stream from tuner provider"); _logger.Info("Opening recording stream from tuner provider");
@ -1058,7 +1148,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
mediaStreamInfo.RunTimeTicks = duration.Ticks; mediaStreamInfo.RunTimeTicks = duration.Ticks;
} }
await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken).ConfigureAwait(false); await
recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken)
.ConfigureAwait(false);
recordingStatus = RecordingStatus.Completed; recordingStatus = RecordingStatus.Completed;
_logger.Info("Recording completed: {0}", recordPath); _logger.Info("Recording completed: {0}", recordPath);
@ -1092,14 +1184,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
ActiveRecordingInfo removed; ActiveRecordingInfo removed;
_activeRecordings.TryRemove(timer.Id, out removed); _activeRecordings.TryRemove(timer.Id, out removed);
if (recordingStatus == RecordingStatus.Completed) if (recordingStatus != RecordingStatus.Completed && DateTime.UtcNow < timer.EndDate)
{
timer.Status = RecordingStatus.Completed;
_timerProvider.Delete(timer);
OnSuccessfulRecording(timer, recordPath);
}
else if (DateTime.UtcNow < timer.EndDate)
{ {
const int retryIntervalSeconds = 60; const int retryIntervalSeconds = 60;
_logger.Info("Retrying recording in {0} seconds.", retryIntervalSeconds); _logger.Info("Retrying recording in {0} seconds.", retryIntervalSeconds);
@ -1108,6 +1193,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
timer.StartDate = DateTime.UtcNow.AddSeconds(retryIntervalSeconds); timer.StartDate = DateTime.UtcNow.AddSeconds(retryIntervalSeconds);
_timerProvider.AddOrUpdate(timer); _timerProvider.AddOrUpdate(timer);
} }
else if (File.Exists(recordPath))
{
timer.Status = RecordingStatus.Completed;
_timerProvider.AddOrUpdate(timer, false);
OnSuccessfulRecording(timer, recordPath);
}
else else
{ {
_timerProvider.Delete(timer); _timerProvider.Delete(timer);
@ -1353,41 +1444,78 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return _config.GetConfiguration<LiveTvOptions>("livetv"); return _config.GetConfiguration<LiveTvOptions>("livetv");
} }
private bool ShouldCancelTimerForSeriesTimer(SeriesTimerInfo seriesTimer, TimerInfo timer)
{
return seriesTimer.SkipEpisodesInLibrary && IsProgramAlreadyInLibrary(timer);
}
private async Task UpdateTimersForSeriesTimer(List<ProgramInfo> epgData, SeriesTimerInfo seriesTimer, bool deleteInvalidTimers) private async Task UpdateTimersForSeriesTimer(List<ProgramInfo> epgData, SeriesTimerInfo seriesTimer, bool deleteInvalidTimers)
{ {
var newTimers = GetTimersForSeries(seriesTimer, epgData, true).ToList(); var allTimers = GetTimersForSeries(seriesTimer, epgData)
.ToList();
var registration = await _liveTvManager.GetRegistrationInfo("seriesrecordings").ConfigureAwait(false); var registration = await _liveTvManager.GetRegistrationInfo("seriesrecordings").ConfigureAwait(false);
if (registration.IsValid) if (registration.IsValid)
{ {
foreach (var timer in newTimers) foreach (var timer in allTimers)
{ {
_timerProvider.AddOrUpdate(timer); var existingTimer = _timerProvider
.GetAll()
.FirstOrDefault(i => string.Equals(i.Id, timer.Id, StringComparison.OrdinalIgnoreCase));
if (existingTimer == null)
{
if (ShouldCancelTimerForSeriesTimer(seriesTimer, timer))
{
timer.Status = RecordingStatus.Cancelled;
}
_timerProvider.Add(timer);
}
else
{
// Only update if not currently active
ActiveRecordingInfo activeRecordingInfo;
if (!_activeRecordings.TryGetValue(timer.Id, out activeRecordingInfo))
{
UpdateExistingTimerWithNewData(existingTimer, timer);
if (ShouldCancelTimerForSeriesTimer(seriesTimer, timer))
{
existingTimer.Status = RecordingStatus.Cancelled;
}
_timerProvider.Update(existingTimer);
}
}
} }
} }
if (deleteInvalidTimers) if (deleteInvalidTimers)
{ {
var allTimers = GetTimersForSeries(seriesTimer, epgData, false) var allTimerIds = allTimers
.Select(i => i.Id) .Select(i => i.Id)
.ToList(); .ToList();
var deleteStatuses = new List<RecordingStatus>
{
RecordingStatus.New
};
var deletes = _timerProvider.GetAll() var deletes = _timerProvider.GetAll()
.Where(i => string.Equals(i.SeriesTimerId, seriesTimer.Id, StringComparison.OrdinalIgnoreCase)) .Where(i => string.Equals(i.SeriesTimerId, seriesTimer.Id, StringComparison.OrdinalIgnoreCase))
.Where(i => !allTimers.Contains(i.Id, StringComparer.OrdinalIgnoreCase) && i.StartDate > DateTime.UtcNow) .Where(i => !allTimerIds.Contains(i.Id, StringComparer.OrdinalIgnoreCase) && i.StartDate > DateTime.UtcNow)
.Where(i => deleteStatuses.Contains(i.Status))
.ToList(); .ToList();
foreach (var timer in deletes) foreach (var timer in deletes)
{ {
await CancelTimerAsync(timer.Id, CancellationToken.None).ConfigureAwait(false); CancelTimerInternal(timer.Id, false);
} }
} }
} }
private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer, private IEnumerable<TimerInfo> GetTimersForSeries(SeriesTimerInfo seriesTimer,
IEnumerable<ProgramInfo> allPrograms, IEnumerable<ProgramInfo> allPrograms)
bool filterByCurrentRecordings)
{ {
if (seriesTimer == null) if (seriesTimer == null)
{ {
@ -1403,15 +1531,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
allPrograms = GetProgramsForSeries(seriesTimer, allPrograms); allPrograms = GetProgramsForSeries(seriesTimer, allPrograms);
if (filterByCurrentRecordings && seriesTimer.SkipEpisodesInLibrary)
{
allPrograms = allPrograms.Where(i => !IsProgramAlreadyInLibrary(i));
}
return allPrograms.Select(i => RecordingHelper.CreateTimer(i, seriesTimer)); return allPrograms.Select(i => RecordingHelper.CreateTimer(i, seriesTimer));
} }
private bool IsProgramAlreadyInLibrary(ProgramInfo program) private bool IsProgramAlreadyInLibrary(TimerInfo program)
{ {
if ((program.EpisodeNumber.HasValue && program.SeasonNumber.HasValue) || !string.IsNullOrWhiteSpace(program.EpisodeTitle)) if ((program.EpisodeNumber.HasValue && program.SeasonNumber.HasValue) || !string.IsNullOrWhiteSpace(program.EpisodeTitle))
{ {

View file

@ -32,7 +32,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
foreach (var item in GetAll().ToList()) foreach (var item in GetAll().ToList())
{ {
AddTimer(item); AddOrUpdateSystemTimer(item);
} }
} }
@ -55,17 +55,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public override void Update(TimerInfo item) public override void Update(TimerInfo item)
{ {
base.Update(item); base.Update(item);
AddOrUpdateSystemTimer(item);
Timer timer;
if (_timers.TryGetValue(item.Id, out timer))
{
var timespan = RecordingHelper.GetStartTime(item) - DateTime.UtcNow;
timer.Change(timespan, TimeSpan.Zero);
}
else
{
AddTimer(item);
}
} }
public void AddOrUpdate(TimerInfo item, bool resetTimer) public void AddOrUpdate(TimerInfo item, bool resetTimer)
@ -96,12 +86,25 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
} }
base.Add(item); base.Add(item);
AddTimer(item); AddOrUpdateSystemTimer(item);
} }
private void AddTimer(TimerInfo item) private bool ShouldStartTimer(TimerInfo item)
{ {
if (item.Status == RecordingStatus.Completed) if (item.Status == RecordingStatus.Completed ||
item.Status == RecordingStatus.Cancelled)
{
return false;
}
return true;
}
private void AddOrUpdateSystemTimer(TimerInfo item)
{
StopTimer(item);
if (!ShouldStartTimer(item))
{ {
return; return;
} }
@ -115,14 +118,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return; return;
} }
var timerLength = startDate - now; var dueTime = startDate - now;
StartTimer(item, timerLength); StartTimer(item, dueTime);
} }
public void StartTimer(TimerInfo item, TimeSpan dueTime) private void StartTimer(TimerInfo item, TimeSpan dueTime)
{ {
StopTimer(item);
var timer = new Timer(TimerCallback, item.Id, dueTime, TimeSpan.Zero); var timer = new Timer(TimerCallback, item.Id, dueTime, TimeSpan.Zero);
if (_timers.TryAdd(item.Id, timer)) if (_timers.TryAdd(item.Id, timer))

View file

@ -102,6 +102,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
RecordAnyTime = info.RecordAnyTime, RecordAnyTime = info.RecordAnyTime,
SkipEpisodesInLibrary = info.SkipEpisodesInLibrary, SkipEpisodesInLibrary = info.SkipEpisodesInLibrary,
KeepUpTo = info.KeepUpTo, KeepUpTo = info.KeepUpTo,
KeepUntil = info.KeepUntil,
RecordNewOnly = info.RecordNewOnly, RecordNewOnly = info.RecordNewOnly,
ExternalChannelId = info.ChannelId, ExternalChannelId = info.ChannelId,
ExternalProgramId = info.ProgramId, ExternalProgramId = info.ProgramId,
@ -312,6 +313,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
RecordAnyTime = dto.RecordAnyTime, RecordAnyTime = dto.RecordAnyTime,
SkipEpisodesInLibrary = dto.SkipEpisodesInLibrary, SkipEpisodesInLibrary = dto.SkipEpisodesInLibrary,
KeepUpTo = dto.KeepUpTo, KeepUpTo = dto.KeepUpTo,
KeepUntil = dto.KeepUntil,
RecordNewOnly = dto.RecordNewOnly, RecordNewOnly = dto.RecordNewOnly,
ProgramId = dto.ExternalProgramId, ProgramId = dto.ExternalProgramId,
ChannelId = dto.ExternalChannelId, ChannelId = dto.ExternalChannelId,

View file

@ -8,7 +8,7 @@
</nlog> </nlog>
<appSettings> <appSettings>
<add key="DebugProgramDataPath" value="ProgramData-Server"/> <add key="DebugProgramDataPath" value="ProgramData-Server"/>
<add key="ReleaseProgramDataPath" value="%ApplicationData%/emby"/> <add key="ReleaseProgramDataPath" value="ProgramData-Server"/>
</appSettings> </appSettings>
<runtime> <runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">

View file

@ -1219,7 +1219,7 @@ namespace MediaBrowser.Server.Startup.Common
var apiUrl = GetLocalApiUrl(address); var apiUrl = GetLocalApiUrl(address);
apiUrl += "/system/ping"; apiUrl += "/system/ping";
if ((DateTime.UtcNow - _lastAddressCacheClear).TotalMinutes >= 5) if ((DateTime.UtcNow - _lastAddressCacheClear).TotalMinutes >= 10)
{ {
_lastAddressCacheClear = DateTime.UtcNow; _lastAddressCacheClear = DateTime.UtcNow;
_validAddressResults.Clear(); _validAddressResults.Clear();