aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Dlna/ContentDirectory/ControlHandler.cs18
-rw-r--r--Emby.Dlna/Didl/DidlBuilder.cs16
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs81
-rw-r--r--Emby.Server.Implementations/Emby.Server.Implementations.csproj1
-rw-r--r--Emby.Server.Implementations/IO/LibraryMonitor.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs17
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs108
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs24
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs129
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs22
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs1
-rw-r--r--Emby.Server.Implementations/Localization/Core/core.json179
-rw-r--r--Emby.Server.Implementations/Localization/Core/en-US.json14
-rw-r--r--Emby.Server.Implementations/Localization/LocalizationManager.cs2
-rw-r--r--Emby.Server.Implementations/Updates/InstallationManager.cs10
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs10
-rw-r--r--MediaBrowser.Controller/Entities/IHasMediaSources.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs39
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs4
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs9
-rw-r--r--MediaBrowser.Controller/LiveTv/TimerInfo.cs3
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs10
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs5
-rw-r--r--MediaBrowser.Model/Configuration/EncodingOptions.cs3
-rw-r--r--MediaBrowser.Model/Dlna/ITranscoderSupport.cs5
-rw-r--r--MediaBrowser.Model/Dlna/StreamBuilder.cs19
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs28
-rw-r--r--MediaBrowser.Model/Dto/MediaSourceInfo.cs1
-rw-r--r--MediaBrowser.Model/LiveTv/LiveTvOptions.cs1
-rw-r--r--MediaBrowser.Providers/TV/MissingEpisodeProvider.cs13
-rw-r--r--MediaBrowser.Server.Mac.sln68
-rw-r--r--MediaBrowser.Server.Mac/Emby.Server.Mac.csproj4
-rw-r--r--MediaBrowser.Server.Mac/MacAppHost.cs4
-rw-r--r--MediaBrowser.Server.Mac/Main.cs36
-rw-r--r--MediaBrowser.Server.Mac/Native/MonoFileSystem.cs2
-rw-r--r--Nuget/MediaBrowser.Common.nuspec2
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec4
-rw-r--r--SharedVersion.cs2
39 files changed, 433 insertions, 469 deletions
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs
index 5ce1d1925..205f4e890 100644
--- a/Emby.Dlna/ContentDirectory/ControlHandler.cs
+++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs
@@ -508,23 +508,6 @@ namespace Emby.Dlna.ContentDirectory
if (stubType.HasValue)
{
- if (stubType.Value == StubType.People)
- {
- var items = _libraryManager.GetPeopleItems(new InternalPeopleQuery
- {
- ItemId = item.Id
-
- });
-
- var result = new QueryResult<ServerItem>
- {
- Items = items.Select(i => new ServerItem(i)).ToArray(items.Count),
- TotalRecordCount = items.Count
- };
-
- return ApplyPaging(result, startIndex, limit);
- }
-
var person = item as Person;
if (person != null)
{
@@ -1356,7 +1339,6 @@ namespace Emby.Dlna.ContentDirectory
public enum StubType
{
Folder = 0,
- People = 1,
Latest = 2,
Playlists = 3,
Albums = 4,
diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs
index 65410bd67..844a6a5ce 100644
--- a/Emby.Dlna/Didl/DidlBuilder.cs
+++ b/Emby.Dlna/Didl/DidlBuilder.cs
@@ -236,7 +236,7 @@ namespace Emby.Dlna.Didl
AddVideoResource(writer, video, deviceId, filter, contentFeature, streamInfo);
}
- var subtitleProfiles = streamInfo.GetSubtitleProfiles(false, _serverAddress, _accessToken)
+ var subtitleProfiles = streamInfo.GetSubtitleProfiles(_mediaEncoder, false, _serverAddress, _accessToken)
.Where(subtitle => subtitle.DeliveryMethod == SubtitleDeliveryMethod.External)
.ToList();
@@ -391,14 +391,6 @@ namespace Emby.Dlna.Didl
private string GetDisplayName(BaseItem item, StubType? itemStubType, BaseItem context)
{
- if (itemStubType.HasValue && itemStubType.Value == StubType.People)
- {
- if (item is Video)
- {
- return _localization.GetLocalizedString("HeaderCastCrew");
- }
- return _localization.GetLocalizedString("HeaderPeople");
- }
if (itemStubType.HasValue && itemStubType.Value == StubType.Latest)
{
return _localization.GetLocalizedString("ViewTypeMusicLatest");
@@ -961,12 +953,6 @@ namespace Emby.Dlna.Didl
private void AddCover(BaseItem item, BaseItem context, StubType? stubType, XmlWriter writer)
{
- if (stubType.HasValue && stubType.Value == StubType.People)
- {
- AddEmbeddedImageAsCover("people", writer);
- return;
- }
-
ImageDownloadInfo imageInfo = null;
if (context is UserView)
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index 9dbf299ab..17e91bfa8 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -115,14 +115,10 @@ namespace Emby.Server.Implementations.Dto
var programTuples = new List<Tuple<BaseItem, BaseItemDto>>();
var channelTuples = new List<Tuple<BaseItemDto, LiveTvChannel>>();
- var refreshQueue = options.Fields.Contains(ItemFields.RefreshState)
- ? _providerManager.GetRefreshQueue()
- : null;
-
var index = 0;
foreach (var item in items)
{
- var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user, owner);
+ var dto = GetBaseItemDtoInternal(item, options, user, owner);
var tvChannel = item as LiveTvChannel;
if (tvChannel != null)
@@ -176,11 +172,7 @@ namespace Emby.Server.Implementations.Dto
{
var syncDictionary = GetSyncedItemProgress(options);
- var refreshQueue = options.Fields.Contains(ItemFields.RefreshState)
- ? _providerManager.GetRefreshQueue()
- : null;
-
- var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user, owner);
+ var dto = GetBaseItemDtoInternal(item, options, user, owner);
var tvChannel = item as LiveTvChannel;
if (tvChannel != null)
{
@@ -312,7 +304,7 @@ namespace Emby.Server.Implementations.Dto
}
}
- private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, Dictionary<Guid, Guid> currentRefreshQueue, User user = null, BaseItem owner = null)
+ private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User user = null, BaseItem owner = null)
{
var fields = options.Fields;
@@ -377,6 +369,8 @@ namespace Emby.Server.Implementations.Dto
{
dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user);
}
+
+ NormalizeMediaSourceContainers(dto);
}
}
@@ -412,25 +406,72 @@ namespace Emby.Server.Implementations.Dto
dto.Etag = item.GetEtag(user);
}
- if (currentRefreshQueue != null)
+ var liveTvManager = _livetvManager();
+ if (item is ILiveTvRecording)
{
- //dto.RefreshState = item.GetRefreshState(currentRefreshQueue);
+ liveTvManager.AddInfoToRecordingDto(item, dto, user);
}
-
- if (item is ILiveTvRecording)
+ else
{
- _livetvManager().AddInfoToRecordingDto(item, dto, user);
+ var activeRecording = liveTvManager.GetActiveRecordingInfo(item.Path);
+ if (activeRecording != null)
+ {
+ dto.Type = "Recording";
+ dto.CanDownload = false;
+ if (!string.IsNullOrWhiteSpace(dto.SeriesName))
+ {
+ dto.EpisodeTitle = dto.Name;
+ dto.Name = dto.SeriesName;
+ }
+ liveTvManager.AddInfoToRecordingDto(item, dto, activeRecording, user);
+ }
}
return dto;
}
+ private void NormalizeMediaSourceContainers(BaseItemDto dto)
+ {
+ foreach (var mediaSource in dto.MediaSources)
+ {
+ var container = mediaSource.Container;
+ if (string.IsNullOrWhiteSpace(container))
+ {
+ continue;
+ }
+ var containers = container.Split(new[] { ',' });
+ if (containers.Length < 2)
+ {
+ continue;
+ }
+
+ var path = mediaSource.Path;
+ string fileExtensionContainer = null;
+
+ if (!string.IsNullOrWhiteSpace(path))
+ {
+ path = Path.GetExtension(path);
+ if (!string.IsNullOrWhiteSpace(path))
+ {
+ path = Path.GetExtension(path);
+ if (!string.IsNullOrWhiteSpace(path))
+ {
+ path = path.TrimStart('.');
+ }
+ if (!string.IsNullOrWhiteSpace(path) && containers.Contains(path, StringComparer.OrdinalIgnoreCase))
+ {
+ fileExtensionContainer = path;
+ }
+ }
+ }
+
+ mediaSource.Container = fileExtensionContainer ?? containers[0];
+ }
+ }
+
public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, Dictionary<string, SyncedItemProgress> syncProgress, User user = null)
{
- var refreshQueue = options.Fields.Contains(ItemFields.RefreshState)
- ? _providerManager.GetRefreshQueue()
- : null;
- var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user);
+ var dto = GetBaseItemDtoInternal(item, options, user);
if (taggedItems != null && options.Fields.Contains(ItemFields.ItemCounts))
{
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 2a45fb315..1dbb10b48 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -698,7 +698,6 @@
<EmbeddedResource Include="Localization\Core\ar.json" />
<EmbeddedResource Include="Localization\Core\bg-BG.json" />
<EmbeddedResource Include="Localization\Core\ca.json" />
- <EmbeddedResource Include="Localization\Core\core.json" />
<EmbeddedResource Include="Localization\Core\cs.json" />
<EmbeddedResource Include="Localization\Core\da.json" />
<EmbeddedResource Include="Localization\Core\de.json" />
diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs
index 1467d9426..3994e2b00 100644
--- a/Emby.Server.Implementations/IO/LibraryMonitor.cs
+++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs
@@ -85,6 +85,8 @@ namespace Emby.Server.Implementations.IO
public bool IsPathLocked(string path)
{
+ // This method is not used by the core but it used by auto-organize
+
var lockedPaths = _tempIgnoredPaths.Keys.ToList();
return lockedPaths.Any(i => _fileSystem.AreEqual(i, path) || _fileSystem.ContainsSubPath(i, path));
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
index 84ceac65e..830bd9d85 100644
--- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
@@ -1,6 +1,8 @@
-using MediaBrowser.Controller.Configuration;
+using System.Globalization;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Globalization;
using MediaBrowser.Naming.Common;
using MediaBrowser.Naming.TV;
@@ -17,15 +19,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+ private readonly ILocalizationManager _localization;
/// <summary>
/// Initializes a new instance of the <see cref="SeasonResolver"/> class.
/// </summary>
/// <param name="config">The config.</param>
- public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager)
+ public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization)
{
_config = config;
_libraryManager = libraryManager;
+ _localization = localization;
}
/// <summary>
@@ -47,9 +52,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
SeriesName = series.Name
};
- if (season.IndexNumber.HasValue && season.IndexNumber.Value == 0)
+ if (season.IndexNumber.HasValue)
{
- season.Name = _config.Configuration.SeasonZeroDisplayName;
+ var seasonNumber = season.IndexNumber.Value;
+
+ season.Name = seasonNumber == 0 ?
+ _config.Configuration.SeasonZeroDisplayName :
+ string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture));
}
return season;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index ecad5c0eb..f3d40ae19 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -830,6 +830,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
existingTimer.IsKids = updatedTimer.IsKids;
existingTimer.IsNews = updatedTimer.IsNews;
existingTimer.IsMovie = updatedTimer.IsMovie;
+ existingTimer.IsSeries = updatedTimer.IsSeries;
+ existingTimer.IsLive = updatedTimer.IsLive;
+ existingTimer.IsPremiere = updatedTimer.IsPremiere;
existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries;
existingTimer.IsRepeat = updatedTimer.IsRepeat;
existingTimer.IsSports = updatedTimer.IsSports;
@@ -861,7 +864,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public async Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken)
{
- return _activeRecordings.Values.ToList().Select(GetRecordingInfo).ToList();
+ return new List<RecordingInfo>();
+ //return _activeRecordings.Values.ToList().Select(GetRecordingInfo).ToList();
}
public string GetActiveRecordingPath(string id)
@@ -875,6 +879,28 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return null;
}
+ public IEnumerable<ActiveRecordingInfo> GetAllActiveRecordings()
+ {
+ return _activeRecordings.Values;
+ }
+
+ public ActiveRecordingInfo GetActiveRecordingInfo(string path)
+ {
+ if (string.IsNullOrWhiteSpace(path))
+ {
+ return null;
+ }
+
+ foreach (var recording in _activeRecordings.Values)
+ {
+ if (string.Equals(recording.Path, path, StringComparison.Ordinal))
+ {
+ return recording;
+ }
+ }
+ return null;
+ }
+
private RecordingInfo GetRecordingInfo(ActiveRecordingInfo info)
{
var timer = info.Timer;
@@ -1245,6 +1271,33 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
throw new FileNotFoundException();
}
+ public async Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(ActiveRecordingInfo info, CancellationToken cancellationToken)
+ {
+ var stream = new MediaSourceInfo
+ {
+ Path = _appHost.GetLocalApiUrl("127.0.0.1") + "/LiveTv/LiveRecordings/" + info.Id + "/stream",
+ Id = info.Id,
+ SupportsDirectPlay = false,
+ SupportsDirectStream = true,
+ SupportsTranscoding = true,
+ IsInfiniteStream = true,
+ RequiresOpening = false,
+ RequiresClosing = false,
+ Protocol = MediaBrowser.Model.MediaInfo.MediaProtocol.Http,
+ BufferMs = 0,
+ IgnoreDts = true,
+ IgnoreIndex = true
+ };
+
+ var isAudio = false;
+ await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
+
+ return new List<MediaSourceInfo>
+ {
+ stream
+ };
+ }
+
public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
{
// Ignore the consumer id
@@ -1327,7 +1380,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var activeRecordingInfo = new ActiveRecordingInfo
{
CancellationTokenSource = new CancellationTokenSource(),
- Timer = timer
+ Timer = timer,
+ Id = timer.Id
};
if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo))
@@ -1493,7 +1547,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath);
recordPath = EnsureFileUnique(recordPath, timer.Id);
- _libraryManager.RegisterIgnoredPath(recordPath);
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath));
activeRecordingInfo.Path = recordPath;
@@ -1512,6 +1565,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_timerProvider.AddOrUpdate(timer, false);
SaveRecordingMetadata(timer, recordPath, seriesPath);
+ TriggerRefresh(recordPath);
EnforceKeepUpTo(timer, seriesPath);
};
@@ -1543,7 +1597,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
- _libraryManager.UnRegisterIgnoredPath(recordPath);
+ TriggerRefresh(recordPath);
_libraryMonitor.ReportFileSystemChangeComplete(recordPath, true);
ActiveRecordingInfo removed;
@@ -1574,6 +1628,44 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
OnRecordingStatusChanged();
}
+ private void TriggerRefresh(string path)
+ {
+ var item = GetAffectedBaseItem(_fileSystem.GetDirectoryName(path));
+
+ if (item != null)
+ {
+ item.ChangedExternally();
+ }
+ }
+
+ private BaseItem GetAffectedBaseItem(string path)
+ {
+ BaseItem item = null;
+
+ while (item == null && !string.IsNullOrEmpty(path))
+ {
+ item = _libraryManager.FindByPath(path, null);
+
+ path = _fileSystem.GetDirectoryName(path);
+ }
+
+ if (item != null)
+ {
+ // If the item has been deleted find the first valid parent that still exists
+ while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path))
+ {
+ item = item.GetParent();
+
+ if (item == null)
+ {
+ break;
+ }
+ }
+ }
+
+ return item;
+ }
+
private void OnRecordingStatusChanged()
{
EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs
@@ -2621,14 +2713,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return list;
}
- class ActiveRecordingInfo
- {
- public string Path { get; set; }
- public TimerInfo Timer { get; set; }
- public ProgramInfo Program { get; set; }
- public CancellationTokenSource CancellationTokenSource { get; set; }
- }
-
private const int TunerDiscoveryDurationMs = 3000;
public async Task<List<TunerHostInfo>> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken)
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
index 94be4a02e..b5de6ef01 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
@@ -58,6 +58,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
timerInfo.OriginalAirDate = programInfo.OriginalAirDate;
timerInfo.IsProgramSeries = programInfo.IsSeries;
+ timerInfo.IsSeries = programInfo.IsSeries;
+ timerInfo.IsLive = programInfo.IsLive;
+ timerInfo.IsPremiere = programInfo.IsPremiere;
+
timerInfo.HomePageUrl = programInfo.HomePageUrl;
timerInfo.CommunityRating = programInfo.CommunityRating;
timerInfo.Overview = programInfo.Overview;
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
index e12acf140..6fe3615d3 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
@@ -247,7 +247,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings
ProgramAudio audioType = ProgramAudio.Stereo;
bool repeat = programInfo.@new == null;
- string newID = programInfo.programID + "T" + startAt.Ticks + "C" + channelId;
+
+ var programId = programInfo.programID ?? string.Empty;
+
+ string newID = programId + "T" + startAt.Ticks + "C" + channelId;
if (programInfo.audioProperties != null)
{
@@ -300,7 +303,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
Etag = programInfo.md5
};
- var showId = programInfo.programID ?? string.Empty;
+ var showId = programId;
if (!info.IsSeries)
{
@@ -339,11 +342,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings
if (details.descriptions != null)
{
- if (details.descriptions.description1000 != null)
+ if (details.descriptions.description1000 != null && details.descriptions.description1000.Count > 0)
{
info.Overview = details.descriptions.description1000[0].description;
}
- else if (details.descriptions.description100 != null)
+ else if (details.descriptions.description100 != null && details.descriptions.description100.Count > 0)
{
info.Overview = details.descriptions.description100[0].description;
}
@@ -351,16 +354,19 @@ namespace Emby.Server.Implementations.LiveTv.Listings
if (info.IsSeries)
{
- info.SeriesId = programInfo.programID.Substring(0, 10);
+ info.SeriesId = programId.Substring(0, 10);
if (details.metadata != null)
{
var gracenote = details.metadata.Find(x => x.Gracenote != null).Gracenote;
- info.SeasonNumber = gracenote.season;
-
- if (gracenote.episode > 0)
+ if (gracenote != null)
{
- info.EpisodeNumber = gracenote.episode;
+ info.SeasonNumber = gracenote.season;
+
+ if (gracenote.episode > 0)
+ {
+ info.EpisodeNumber = gracenote.episode;
+ }
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index 2882af007..bf30546ab 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.LiveTv
private readonly LiveTvDtoService _tvDtoService;
- private readonly List<ILiveTvService> _services = new List<ILiveTvService>();
+ private ILiveTvService[] _services = new ILiveTvService[] { };
private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1);
@@ -124,7 +124,7 @@ namespace Emby.Server.Implementations.LiveTv
/// <param name="listingProviders">The listing providers.</param>
public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders)
{
- _services.AddRange(services);
+ _services = services.ToArray();
_tunerHosts.AddRange(tunerHosts);
_listingProviders.AddRange(listingProviders);
@@ -1221,9 +1221,9 @@ namespace Emby.Server.Implementations.LiveTv
await EmbyTV.EmbyTV.Current.ScanForTunerDeviceChanges(cancellationToken).ConfigureAwait(false);
var numComplete = 0;
- double progressPerService = _services.Count == 0
+ double progressPerService = _services.Length == 0
? 0
- : 1 / _services.Count;
+ : 1 / _services.Length;
var newChannelIdList = new List<Guid>();
var newProgramIdList = new List<Guid>();
@@ -1255,7 +1255,7 @@ namespace Emby.Server.Implementations.LiveTv
numComplete++;
double percent = numComplete;
- percent /= _services.Count;
+ percent /= _services.Length;
progress.Report(100 * percent);
}
@@ -1561,11 +1561,6 @@ namespace Emby.Server.Implementations.LiveTv
return new QueryResult<BaseItem>();
}
- if ((query.IsInProgress ?? false))
- {
- return new QueryResult<BaseItem>();
- }
-
var folderIds = EmbyTV.EmbyTV.Current.GetRecordingFolders()
.SelectMany(i => i.Locations)
.Distinct(StringComparer.OrdinalIgnoreCase)
@@ -1577,13 +1572,10 @@ namespace Emby.Server.Implementations.LiveTv
var excludeItemTypes = new List<string>();
- if (!query.IsInProgress.HasValue)
- {
- folderIds.Add(internalLiveTvFolderId);
+ folderIds.Add(internalLiveTvFolderId);
- excludeItemTypes.Add(typeof(LiveTvChannel).Name);
- excludeItemTypes.Add(typeof(LiveTvProgram).Name);
- }
+ excludeItemTypes.Add(typeof(LiveTvChannel).Name);
+ excludeItemTypes.Add(typeof(LiveTvProgram).Name);
if (folderIds.Count == 0)
{
@@ -1632,6 +1624,19 @@ namespace Emby.Server.Implementations.LiveTv
}
}
+ if ((query.IsInProgress ?? false))
+ {
+ // TODO: filter
+ var allActivePaths = EmbyTV.EmbyTV.Current.GetAllActiveRecordings().Select(i => i.Path).ToArray();
+ var items = allActivePaths.Select(i => _libraryManager.FindByPath(i, false)).Where(i => i != null).ToArray();
+
+ return new QueryResult<BaseItem>
+ {
+ Items = items,
+ TotalRecordCount = items.Length
+ };
+ }
+
return _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{
MediaTypes = new[] { MediaType.Video },
@@ -1659,11 +1664,6 @@ namespace Emby.Server.Implementations.LiveTv
return new QueryResult<BaseItemDto>();
}
- if (_services.Count > 1)
- {
- return new QueryResult<BaseItemDto>();
- }
-
if (user == null || (query.IsInProgress ?? false))
{
return new QueryResult<BaseItemDto>();
@@ -1722,13 +1722,9 @@ namespace Emby.Server.Implementations.LiveTv
var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false);
- if (_services.Count == 1 && (!query.IsInProgress.HasValue || !query.IsInProgress.Value) && (!query.IsLibraryItem.HasValue || query.IsLibraryItem.Value))
+ // TODO: Figure out how to merge emby recordings + service recordings
+ if (_services.Length == 1)
{
- if (!query.IsInProgress.HasValue)
- {
- await RefreshRecordings(folder.Id, cancellationToken).ConfigureAwait(false);
- }
-
return GetEmbyRecordings(query, options, folder.Id, user);
}
@@ -1920,6 +1916,11 @@ namespace Emby.Server.Implementations.LiveTv
await AddRecordingInfo(programTuples, CancellationToken.None).ConfigureAwait(false);
}
+ public ActiveRecordingInfo GetActiveRecordingInfo(string path)
+ {
+ return EmbyTV.EmbyTV.Current.GetActiveRecordingInfo(path);
+ }
+
public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, User user = null)
{
var recording = (ILiveTvRecording)item;
@@ -1949,27 +1950,72 @@ namespace Emby.Server.Implementations.LiveTv
dto.IsKids = info.IsKids;
dto.IsPremiere = info.IsPremiere;
- dto.CanDelete = user == null
- ? recording.CanDelete()
- : recording.CanDelete(user);
-
- if (dto.MediaSources == null)
+ if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue)
{
- dto.MediaSources = recording.GetMediaSources(true);
+ var now = DateTime.UtcNow.Ticks;
+ var start = info.StartDate.Ticks;
+ var end = info.EndDate.Value.Ticks;
+
+ var pct = now - start;
+ pct /= end;
+ pct *= 100;
+ dto.CompletionPercentage = pct;
}
- if (dto.MediaStreams == null)
+ if (channel != null)
{
- dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToArray();
+ dto.ChannelName = channel.Name;
+
+ if (channel.HasImage(ImageType.Primary))
+ {
+ dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(channel);
+ }
}
+ }
- if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue)
+ public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordingInfo activeRecordingInfo, User user = null)
+ {
+ var service = EmbyTV.EmbyTV.Current;
+
+ var info = activeRecordingInfo.Timer;
+
+ var channel = string.IsNullOrWhiteSpace(info.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, info.ChannelId));
+
+ dto.SeriesTimerId = string.IsNullOrEmpty(info.SeriesTimerId)
+ ? null
+ : _tvDtoService.GetInternalSeriesTimerId(service.Name, info.SeriesTimerId).ToString("N");
+
+ dto.TimerId = string.IsNullOrEmpty(info.Id)
+ ? null
+ : _tvDtoService.GetInternalTimerId(service.Name, info.Id).ToString("N");
+
+ var startDate = info.StartDate;
+ var endDate = info.EndDate;
+
+ dto.StartDate = startDate;
+ dto.EndDate = endDate;
+ dto.Status = info.Status.ToString();
+ dto.IsRepeat = info.IsRepeat;
+ dto.EpisodeTitle = info.EpisodeTitle;
+ dto.IsMovie = info.IsMovie;
+ dto.IsSeries = info.IsSeries;
+ dto.IsSports = info.IsSports;
+ dto.IsLive = info.IsLive;
+ dto.IsNews = info.IsNews;
+ dto.IsKids = info.IsKids;
+ dto.IsPremiere = info.IsPremiere;
+
+ if (info.Status == RecordingStatus.InProgress)
{
+ startDate = info.StartDate.AddSeconds(0 - info.PrePaddingSeconds);
+ endDate = info.EndDate.AddSeconds(info.PostPaddingSeconds);
+
var now = DateTime.UtcNow.Ticks;
- var start = info.StartDate.Ticks;
- var end = info.EndDate.Value.Ticks;
+ var start = startDate.Ticks;
+ var end = endDate.Ticks;
var pct = now - start;
+
pct /= end;
pct *= 100;
dto.CompletionPercentage = pct;
@@ -2098,7 +2144,6 @@ namespace Emby.Server.Implementations.LiveTv
if (service is EmbyTV.EmbyTV)
{
- // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says
return service.DeleteRecordingAsync(GetItemExternalId(recording), CancellationToken.None);
}
@@ -2348,7 +2393,6 @@ namespace Emby.Server.Implementations.LiveTv
var currentChannelsDict = new Dictionary<string, BaseItemDto>();
var addCurrentProgram = options.AddCurrentProgram;
- var addMediaSources = options.Fields.Contains(ItemFields.MediaSources);
var addServiceName = options.Fields.Contains(ItemFields.ServiceName);
foreach (var tuple in tuples)
@@ -2367,11 +2411,6 @@ namespace Emby.Server.Implementations.LiveTv
currentChannelsDict[dto.Id] = dto;
- if (addMediaSources)
- {
- dto.MediaSources = channel.GetMediaSources(true);
- }
-
if (addCurrentProgram)
{
var channelIdString = channel.Id.ToString("N");
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
index 5436a12b8..0e52f874d 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
@@ -43,9 +43,11 @@ namespace Emby.Server.Implementations.LiveTv
if (baseItem.SourceType == SourceType.LiveTV)
{
- if (string.IsNullOrWhiteSpace(baseItem.Path))
+ var activeRecordingInfo = _liveTvManager.GetActiveRecordingInfo(item.Path);
+
+ if (string.IsNullOrWhiteSpace(baseItem.Path) || activeRecordingInfo != null)
{
- return GetMediaSourcesInternal(item, cancellationToken);
+ return GetMediaSourcesInternal(item, activeRecordingInfo, cancellationToken);
}
}
@@ -56,7 +58,7 @@ namespace Emby.Server.Implementations.LiveTv
private const char StreamIdDelimeter = '_';
private const string StreamIdDelimeterString = "_";
- private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(IHasMediaSources item, CancellationToken cancellationToken)
+ private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(IHasMediaSources item, ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken)
{
IEnumerable<MediaSourceInfo> sources;
@@ -67,12 +69,20 @@ namespace Emby.Server.Implementations.LiveTv
if (item is ILiveTvRecording)
{
sources = await _liveTvManager.GetRecordingMediaSources(item, cancellationToken)
- .ConfigureAwait(false);
+ .ConfigureAwait(false);
}
else
{
- sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken)
- .ConfigureAwait(false);
+ if (activeRecordingInfo != null)
+ {
+ sources = await EmbyTV.EmbyTV.Current.GetRecordingStreamMediaSources(activeRecordingInfo, cancellationToken)
+ .ConfigureAwait(false);
+ }
+ else
+ {
+ sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken)
+ .ConfigureAwait(false);
+ }
}
}
catch (NotImplementedException)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
index 1bc334f06..eac845579 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
@@ -165,6 +165,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
RequiresOpening = true,
RequiresClosing = true,
RequiresLooping = info.EnableStreamLooping,
+ EnableMpDecimate = info.EnableMpDecimate,
ReadAtNativeFramerate = false,
diff --git a/Emby.Server.Implementations/Localization/Core/core.json b/Emby.Server.Implementations/Localization/Core/core.json
deleted file mode 100644
index 976faa8cb..000000000
--- a/Emby.Server.Implementations/Localization/Core/core.json
+++ /dev/null
@@ -1,179 +0,0 @@
-{
- "AppDeviceValues": "App: {0}, Device: {1}",
- "UserDownloadingItemWithValues": "{0} is downloading {1}",
- "FolderTypeMixed": "Mixed content",
- "FolderTypeMovies": "Movies",
- "FolderTypeMusic": "Music",
- "FolderTypeAdultVideos": "Adult videos",
- "FolderTypePhotos": "Photos",
- "FolderTypeMusicVideos": "Music videos",
- "FolderTypeHomeVideos": "Home videos",
- "FolderTypeGames": "Games",
- "FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV",
- "FolderTypeInherit": "Inherit",
- "HeaderCastCrew": "Cast & Crew",
- "HeaderPeople": "People",
- "ValueSpecialEpisodeName": "Special - {0}",
- "LabelChapterName": "Chapter {0}",
- "NameSeasonNumber": "Season {0}",
- "LabelExit": "Exit",
- "LabelVisitCommunity": "Visit Community",
- "LabelGithub": "Github",
- "LabelApiDocumentation": "Api Documentation",
- "LabelDeveloperResources": "Developer Resources",
- "LabelBrowseLibrary": "Browse Library",
- "LabelConfigureServer": "Configure Emby",
- "LabelRestartServer": "Restart Server",
- "CategorySync": "Sync",
- "CategoryUser": "User",
- "CategorySystem": "System",
- "CategoryApplication": "Application",
- "CategoryPlugin": "Plugin",
- "NotificationOptionPluginError": "Plugin failure",
- "NotificationOptionApplicationUpdateAvailable": "Application update available",
- "NotificationOptionApplicationUpdateInstalled": "Application update installed",
- "NotificationOptionPluginUpdateInstalled": "Plugin update installed",
- "NotificationOptionPluginInstalled": "Plugin installed",
- "NotificationOptionPluginUninstalled": "Plugin uninstalled",
- "NotificationOptionVideoPlayback": "Video playback started",
- "NotificationOptionAudioPlayback": "Audio playback started",
- "NotificationOptionGamePlayback": "Game playback started",
- "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
- "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
- "NotificationOptionGamePlaybackStopped": "Game playback stopped",
- "NotificationOptionTaskFailed": "Scheduled task failure",
- "NotificationOptionInstallationFailed": "Installation failure",
- "NotificationOptionNewLibraryContent": "New content added",
- "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
- "NotificationOptionCameraImageUploaded": "Camera image uploaded",
- "NotificationOptionUserLockedOut": "User locked out",
- "NotificationOptionServerRestartRequired": "Server restart required",
- "ViewTypePlaylists": "Playlists",
- "ViewTypeMovies": "Movies",
- "ViewTypeTvShows": "TV",
- "ViewTypeGames": "Games",
- "ViewTypeMusic": "Music",
- "ViewTypeMusicGenres": "Genres",
- "ViewTypeMusicArtists": "Artists",
- "ViewTypeBoxSets": "Collections",
- "ViewTypeChannels": "Channels",
- "ViewTypeLiveTV": "Live TV",
- "ViewTypeLiveTvNowPlaying": "Now Airing",
- "ViewTypeLatestGames": "Latest Games",
- "ViewTypeRecentlyPlayedGames": "Recently Played",
- "ViewTypeGameFavorites": "Favorites",
- "ViewTypeGameSystems": "Game Systems",
- "ViewTypeGameGenres": "Genres",
- "ViewTypeTvResume": "Resume",
- "ViewTypeTvNextUp": "Next Up",
- "ViewTypeTvLatest": "Latest",
- "ViewTypeTvShowSeries": "Series",
- "ViewTypeTvGenres": "Genres",
- "ViewTypeTvFavoriteSeries": "Favorite Series",
- "ViewTypeTvFavoriteEpisodes": "Favorite Episodes",
- "ViewTypeMovieResume": "Resume",
- "ViewTypeMovieLatest": "Latest",
- "ViewTypeMovieMovies": "Movies",
- "ViewTypeMovieCollections": "Collections",
- "ViewTypeMovieFavorites": "Favorites",
- "ViewTypeMovieGenres": "Genres",
- "ViewTypeMusicLatest": "Latest",
- "ViewTypeMusicPlaylists": "Playlists",
- "ViewTypeMusicAlbums": "Albums",
- "ViewTypeMusicAlbumArtists": "Album Artists",
- "HeaderOtherDisplaySettings": "Display Settings",
- "ViewTypeMusicSongs": "Songs",
- "ViewTypeMusicFavorites": "Favorites",
- "ViewTypeMusicFavoriteAlbums": "Favorite Albums",
- "ViewTypeMusicFavoriteArtists": "Favorite Artists",
- "ViewTypeMusicFavoriteSongs": "Favorite Songs",
- "ViewTypeFolders": "Folders",
- "ViewTypeLiveTvRecordingGroups": "Recordings",
- "ViewTypeLiveTvChannels": "Channels",
- "ScheduledTaskFailedWithName": "{0} failed",
- "LabelRunningTimeValue": "Running time: {0}",
- "ScheduledTaskStartedWithName": "{0} started",
- "VersionNumber": "Version {0}",
- "PluginInstalledWithName": "{0} was installed",
- "PluginUpdatedWithName": "{0} was updated",
- "PluginUninstalledWithName": "{0} was uninstalled",
- "ItemAddedWithName": "{0} was added to the library",
- "ItemRemovedWithName": "{0} was removed from the library",
- "LabelIpAddressValue": "Ip address: {0}",
- "DeviceOnlineWithName": "{0} is connected",
- "UserOnlineFromDevice": "{0} is online from {1}",
- "ProviderValue": "Provider: {0}",
- "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
- "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
- "UserCreatedWithName": "User {0} has been created",
- "UserPasswordChangedWithName": "Password has been changed for user {0}",
- "UserDeletedWithName": "User {0} has been deleted",
- "MessageServerConfigurationUpdated": "Server configuration has been updated",
- "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
- "MessageApplicationUpdated": "Emby Server has been updated",
- "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
- "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
- "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}",
- "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
- "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
- "HeaderUnidentified": "Unidentified",
- "HeaderImagePrimary": "Primary",
- "HeaderImageBackdrop": "Backdrop",
- "HeaderImageLogo": "Logo",
- "HeaderUserPrimaryImage": "User Image",
- "HeaderOverview": "Overview",
- "HeaderShortOverview": "Short Overview",
- "HeaderType": "Type",
- "HeaderSeverity": "Severity",
- "HeaderUser": "User",
- "HeaderName": "Name",
- "HeaderDate": "Date",
- "HeaderPremiereDate": "Premiere Date",
- "HeaderDateAdded": "Date Added",
- "HeaderReleaseDate": "Release date",
- "HeaderRuntime": "Runtime",
- "HeaderPlayCount": "Play Count",
- "HeaderSeason": "Season",
- "HeaderSeasonNumber": "Season number",
- "HeaderSeries": "Series:",
- "HeaderNetwork": "Network",
- "HeaderYear": "Year:",
- "HeaderYears": "Years:",
- "HeaderParentalRating": "Parental Rating",
- "HeaderCommunityRating": "Community rating",
- "HeaderTrailers": "Trailers",
- "HeaderSpecials": "Specials",
- "HeaderGameSystems": "Game Systems",
- "HeaderPlayers": "Players:",
- "HeaderAlbumArtists": "Album Artists",
- "HeaderAlbums": "Albums",
- "HeaderDisc": "Disc",
- "HeaderTrack": "Track",
- "HeaderAudio": "Audio",
- "HeaderVideo": "Video",
- "HeaderEmbeddedImage": "Embedded image",
- "HeaderResolution": "Resolution",
- "HeaderSubtitles": "Subtitles",
- "HeaderGenres": "Genres",
- "HeaderCountries": "Countries",
- "HeaderStatus": "Status",
- "HeaderTracks": "Tracks",
- "HeaderMusicArtist": "Music artist",
- "HeaderLocked": "Locked",
- "HeaderStudios": "Studios",
- "HeaderActor": "Actors",
- "HeaderComposer": "Composers",
- "HeaderDirector": "Directors",
- "HeaderGuestStar": "Guest star",
- "HeaderProducer": "Producers",
- "HeaderWriter": "Writers",
- "HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings",
- "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.",
- "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete."
-}
diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json
index 133644ff7..c7f865233 100644
--- a/Emby.Server.Implementations/Localization/Core/en-US.json
+++ b/Emby.Server.Implementations/Localization/Core/en-US.json
@@ -1,5 +1,4 @@
{
- "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.",
"AppDeviceValues": "App: {0}, Device: {1}",
"UserDownloadingItemWithValues": "{0} is downloading {1}",
"FolderTypeMixed": "Mixed content",
@@ -13,15 +12,12 @@
"FolderTypeBooks": "Books",
"FolderTypeTvShows": "TV",
"FolderTypeInherit": "Inherit",
- "HeaderCastCrew": "Cast & Crew",
- "HeaderPeople": "People",
"ValueSpecialEpisodeName": "Special - {0}",
"LabelChapterName": "Chapter {0}",
"NameSeasonUnknown": "Season Unknown",
"NameSeasonNumber": "Season {0}",
"LabelExit": "Exit",
"LabelVisitCommunity": "Visit Community",
- "LabelGithub": "Github",
"LabelApiDocumentation": "Api Documentation",
"LabelDeveloperResources": "Developer Resources",
"LabelBrowseLibrary": "Browse Library",
@@ -164,15 +160,5 @@
"HeaderStatus": "Status",
"HeaderTracks": "Tracks",
"HeaderMusicArtist": "Music artist",
- "HeaderLocked": "Locked",
- "HeaderStudios": "Studios",
- "HeaderActor": "Actors",
- "HeaderComposer": "Composers",
- "HeaderDirector": "Directors",
- "HeaderGuestStar": "Guest star",
- "HeaderProducer": "Producers",
- "HeaderWriter": "Writers",
- "HeaderParentalRatings": "Parental Ratings",
- "HeaderCommunityRatings": "Community ratings",
"StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} \ No newline at end of file
diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs
index a8cd1dc04..278a39cd1 100644
--- a/Emby.Server.Implementations/Localization/LocalizationManager.cs
+++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs
@@ -335,7 +335,7 @@ namespace Emby.Server.Implementations.Localization
const string prefix = "Core";
var key = prefix + culture;
- return _dictionaries.GetOrAdd(key, k => GetDictionary(prefix, culture, "core.json"));
+ return _dictionaries.GetOrAdd(key, k => GetDictionary(prefix, culture, "en-US.json"));
}
private Dictionary<string, string> GetDictionary(string prefix, string culture, string baseFilename)
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index 4d1e1eaac..393fb76e2 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/Emby.Server.Implementations/Updates/InstallationManager.cs
@@ -277,15 +277,7 @@ namespace Emby.Server.Implementations.Updates
private TimeSpan GetCacheLength()
{
- switch (GetSystemUpdateLevel())
- {
- case PackageVersionClass.Beta:
- return TimeSpan.FromMinutes(30);
- case PackageVersionClass.Dev:
- return TimeSpan.FromMinutes(3);
- default:
- return TimeSpan.FromHours(24);
- }
+ return TimeSpan.FromMinutes(3);
}
protected PackageInfo[] FilterPackages(List<PackageInfo> packages)
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index b08834784..11c0a5747 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -648,15 +648,15 @@ namespace MediaBrowser.Controller.Entities
public static bool IsPathOffline(string path, List<string> allLibraryPaths)
{
- if (FileSystem.FileExists(path))
- {
- return false;
- }
+ //if (FileSystem.FileExists(path))
+ //{
+ // return false;
+ //}
var originalPath = path;
// Depending on whether the path is local or unc, it may return either null or '\' at the top
- while (!string.IsNullOrEmpty(path) && path.Length > 1)
+ while (!string.IsNullOrWhiteSpace(path) && path.Length > 1)
{
if (FileSystem.DirectoryExists(path))
{
diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs
index bf4acdfbd..54786134f 100644
--- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs
+++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs
@@ -4,7 +4,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities
{
- public interface IHasMediaSources : IHasUserData
+ public interface IHasMediaSources : IHasMetadata
{
/// <summary>
/// Gets the media sources.
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index fa11787f5..3918ac8fc 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -160,7 +160,7 @@ namespace MediaBrowser.Controller.Entities
public string[] GetPlayableStreamFileNames()
{
- return GetPlayableStreamFiles().Select(System.IO.Path.GetFileName).ToArray();
+ return GetPlayableStreamFiles().Select(System.IO.Path.GetFileName).ToArray();
}
/// <summary>
@@ -235,6 +235,35 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
+ public override SourceType SourceType
+ {
+ get
+ {
+ if (IsActiveRecording())
+ {
+ return SourceType.LiveTV;
+ }
+
+ return base.SourceType;
+ }
+ }
+
+ protected bool IsActiveRecording()
+ {
+ return LiveTvManager.GetActiveRecordingInfo(Path) != null;
+ }
+
+ public override bool CanDelete()
+ {
+ if (IsActiveRecording())
+ {
+ return false;
+ }
+
+ return base.CanDelete();
+ }
+
+ [IgnoreDataMember]
protected virtual bool EnableDefaultVideoUserDataKeys
{
get
@@ -616,6 +645,14 @@ namespace MediaBrowser.Controller.Entities
var list = GetAllVideosForMediaSources();
var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList();
+ if (IsActiveRecording())
+ {
+ foreach (var mediaSource in result)
+ {
+ mediaSource.Type = MediaSourceType.Placeholder;
+ }
+ }
+
return result.OrderBy(i =>
{
if (i.VideoType == VideoType.VideoFile)
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index 862894f61..6ff630590 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -384,5 +384,9 @@ namespace MediaBrowser.Controller.LiveTv
string GetEmbyTvActiveRecordingPath(string id);
Task<LiveStream> GetEmbyTvLiveStream(string id);
+
+ ActiveRecordingInfo GetActiveRecordingInfo(string path);
+
+ void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordingInfo activeRecordingInfo, User user = null);
}
}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
index 43fc307f4..4b757f0b9 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
@@ -36,4 +36,13 @@ namespace MediaBrowser.Controller.LiveTv
DateTime? EndDate { get; set; }
DateTime DateCreated { get; set; }
}
+
+ public class ActiveRecordingInfo
+ {
+ public string Id { get; set; }
+ public string Path { get; set; }
+ public TimerInfo Timer { get; set; }
+ public ProgramInfo Program { get; set; }
+ public CancellationTokenSource CancellationTokenSource { get; set; }
+ }
}
diff --git a/MediaBrowser.Controller/LiveTv/TimerInfo.cs b/MediaBrowser.Controller/LiveTv/TimerInfo.cs
index 0b94c85fa..a0002241d 100644
--- a/MediaBrowser.Controller/LiveTv/TimerInfo.cs
+++ b/MediaBrowser.Controller/LiveTv/TimerInfo.cs
@@ -109,6 +109,9 @@ namespace MediaBrowser.Controller.LiveTv
public bool IsKids { get; set; }
public bool IsSports { get; set; }
public bool IsNews { get; set; }
+ public bool IsSeries { get; set; }
+ public bool IsLive { get; set; }
+ public bool IsPremiere { get; set; }
public int? ProductionYear { get; set; }
public string EpisodeTitle { get; set; }
public DateTime? OriginalAirDate { get; set; }
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index d99103852..736f1b32f 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -778,6 +778,11 @@ namespace MediaBrowser.Controller.MediaEncoding
return false;
}
+ if (state.EnableMpDecimate)
+ {
+ return false;
+ }
+
if (videoStream.IsInterlaced)
{
if (request.DeInterlace)
@@ -1449,6 +1454,11 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
+ if (state.EnableMpDecimate)
+ {
+ filters.Add("mpdecimate,setpts=N/FRAME_RATE/TB");
+ }
+
if (filters.Count > 0)
{
output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray()));
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
index c2ce96979..e76217fda 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
@@ -127,6 +127,11 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
+ public bool EnableMpDecimate
+ {
+ get { return MediaSource.EnableMpDecimate; }
+ }
+
public string AlbumCoverPath { get; set; }
public string InputAudioSync { get; set; }
diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs
index d619e3140..b093d82e3 100644
--- a/MediaBrowser.Model/Configuration/EncodingOptions.cs
+++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs
@@ -14,6 +14,7 @@ namespace MediaBrowser.Model.Configuration
public int H264Crf { get; set; }
public string H264Preset { get; set; }
public bool EnableHardwareEncoding { get; set; }
+ public bool EnableSubtitleExtraction { get; set; }
public string[] HardwareDecodingCodecs { get; set; }
@@ -26,7 +27,7 @@ namespace MediaBrowser.Model.Configuration
VaapiDevice = "/dev/dri/card0";
H264Crf = 23;
EnableHardwareEncoding = true;
-
+ EnableSubtitleExtraction = true;
HardwareDecodingCodecs = new string[] { "h264", "vc1" };
}
}
diff --git a/MediaBrowser.Model/Dlna/ITranscoderSupport.cs b/MediaBrowser.Model/Dlna/ITranscoderSupport.cs
index fd615733d..14723bd27 100644
--- a/MediaBrowser.Model/Dlna/ITranscoderSupport.cs
+++ b/MediaBrowser.Model/Dlna/ITranscoderSupport.cs
@@ -4,6 +4,7 @@
{
bool CanEncodeToAudioCodec(string codec);
bool CanEncodeToSubtitleCodec(string codec);
+ bool CanExtractSubtitles(string codec);
}
public class FullTranscoderSupport : ITranscoderSupport
@@ -16,5 +17,9 @@
{
return true;
}
+ public bool CanExtractSubtitles(string codec)
+ {
+ return true;
+ }
}
}
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index 1cb783669..10c6a05c0 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -686,7 +686,7 @@ namespace MediaBrowser.Model.Dlna
if (subtitleStream != null)
{
- SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, directPlay.Value, null, null);
+ SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, directPlay.Value, _transcoderSupport, null, null);
playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
playlistItem.SubtitleFormat = subtitleProfile.Format;
@@ -728,7 +728,7 @@ namespace MediaBrowser.Model.Dlna
if (subtitleStream != null)
{
- SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode, transcodingProfile.Protocol, transcodingProfile.Container);
+ SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode, _transcoderSupport, transcodingProfile.Protocol, transcodingProfile.Container);
playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method;
playlistItem.SubtitleFormat = subtitleProfile.Format;
@@ -1183,7 +1183,7 @@ namespace MediaBrowser.Model.Dlna
{
if (subtitleStream != null)
{
- SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, playMethod, null, null);
+ SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, playMethod, _transcoderSupport, null, null);
if (subtitleProfile.Method != SubtitleDeliveryMethod.External && subtitleProfile.Method != SubtitleDeliveryMethod.Embed)
{
@@ -1202,7 +1202,7 @@ namespace MediaBrowser.Model.Dlna
return new Tuple<bool, TranscodeReason?>(result, TranscodeReason.ContainerBitrateExceedsLimit);
}
- public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, string transcodingSubProtocol, string transcodingContainer)
+ public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, ITranscoderSupport transcoderSupport, string transcodingSubProtocol, string transcodingContainer)
{
if (!subtitleStream.IsExternal && (playMethod != PlayMethod.Transcode || !string.Equals(transcodingSubProtocol, "hls", StringComparison.OrdinalIgnoreCase)))
{
@@ -1256,7 +1256,9 @@ namespace MediaBrowser.Model.Dlna
}
// Look for an external or hls profile that matches the stream type (text/graphical) and doesn't require conversion
- return GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, false) ?? GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, true) ?? new SubtitleProfile
+ return GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, transcoderSupport, false) ??
+ GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, transcoderSupport, true) ??
+ new SubtitleProfile
{
Method = SubtitleDeliveryMethod.Encode,
Format = subtitleStream.Codec
@@ -1291,7 +1293,7 @@ namespace MediaBrowser.Model.Dlna
return false;
}
- private static SubtitleProfile GetExternalSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, bool allowConversion)
+ private static SubtitleProfile GetExternalSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, ITranscoderSupport transcoderSupport, bool allowConversion)
{
foreach (SubtitleProfile profile in subtitleProfiles)
{
@@ -1310,6 +1312,11 @@ namespace MediaBrowser.Model.Dlna
continue;
}
+ if (!subtitleStream.IsExternal && !transcoderSupport.CanExtractSubtitles(subtitleStream.Codec))
+ {
+ continue;
+ }
+
if ((profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format)) ||
(profile.Method == SubtitleDeliveryMethod.Hls && subtitleStream.IsTextSubtitleStream))
{
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index f863d8c95..c63e74eaf 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -309,14 +309,14 @@ namespace MediaBrowser.Model.Dlna
return list;
}
- public List<SubtitleStreamInfo> GetExternalSubtitles(bool includeSelectedTrackOnly, string baseUrl, string accessToken)
+ public List<SubtitleStreamInfo> GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken)
{
- return GetExternalSubtitles(includeSelectedTrackOnly, false, baseUrl, accessToken);
+ return GetExternalSubtitles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken);
}
- public List<SubtitleStreamInfo> GetExternalSubtitles(bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken)
+ public List<SubtitleStreamInfo> GetExternalSubtitles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken)
{
- List<SubtitleStreamInfo> list = GetSubtitleProfiles(includeSelectedTrackOnly, enableAllProfiles, baseUrl, accessToken);
+ List<SubtitleStreamInfo> list = GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, enableAllProfiles, baseUrl, accessToken);
List<SubtitleStreamInfo> newList = new List<SubtitleStreamInfo>();
// First add the selected track
@@ -331,12 +331,12 @@ namespace MediaBrowser.Model.Dlna
return newList;
}
- public List<SubtitleStreamInfo> GetSubtitleProfiles(bool includeSelectedTrackOnly, string baseUrl, string accessToken)
+ public List<SubtitleStreamInfo> GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, string baseUrl, string accessToken)
{
- return GetSubtitleProfiles(includeSelectedTrackOnly, false, baseUrl, accessToken);
+ return GetSubtitleProfiles(transcoderSupport, includeSelectedTrackOnly, false, baseUrl, accessToken);
}
- public List<SubtitleStreamInfo> GetSubtitleProfiles(bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken)
+ public List<SubtitleStreamInfo> GetSubtitleProfiles(ITranscoderSupport transcoderSupport, bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken)
{
List<SubtitleStreamInfo> list = new List<SubtitleStreamInfo>();
@@ -352,7 +352,7 @@ namespace MediaBrowser.Model.Dlna
{
if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value)
{
- AddSubtitleProfiles(list, stream, enableAllProfiles, baseUrl, accessToken, startPositionTicks);
+ AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks);
}
}
}
@@ -363,7 +363,7 @@ namespace MediaBrowser.Model.Dlna
{
if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value))
{
- AddSubtitleProfiles(list, stream, enableAllProfiles, baseUrl, accessToken, startPositionTicks);
+ AddSubtitleProfiles(list, stream, transcoderSupport, enableAllProfiles, baseUrl, accessToken, startPositionTicks);
}
}
}
@@ -371,28 +371,28 @@ namespace MediaBrowser.Model.Dlna
return list;
}
- private void AddSubtitleProfiles(List<SubtitleStreamInfo> list, MediaStream stream, bool enableAllProfiles, string baseUrl, string accessToken, long startPositionTicks)
+ private void AddSubtitleProfiles(List<SubtitleStreamInfo> list, MediaStream stream, ITranscoderSupport transcoderSupport, bool enableAllProfiles, string baseUrl, string accessToken, long startPositionTicks)
{
if (enableAllProfiles)
{
foreach (SubtitleProfile profile in DeviceProfile.SubtitleProfiles)
{
- SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile });
+ SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile }, transcoderSupport);
list.Add(info);
}
}
else
{
- SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles);
+ SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles, transcoderSupport);
list.Add(info);
}
}
- private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles)
+ private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles, ITranscoderSupport transcoderSupport)
{
- SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, subtitleProfiles, PlayMethod, SubProtocol, Container);
+ SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, subtitleProfiles, PlayMethod, transcoderSupport, SubProtocol, Container);
SubtitleStreamInfo info = new SubtitleStreamInfo
{
IsForced = stream.IsForced,
diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs
index 488b1e7a8..8f3f0648d 100644
--- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs
+++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs
@@ -41,6 +41,7 @@ namespace MediaBrowser.Model.Dto
public string OpenToken { get; set; }
public bool RequiresClosing { get; set; }
public bool SupportsProbing { get; set; }
+ public bool EnableMpDecimate { get; set; }
public string LiveStreamId { get; set; }
public int? BufferMs { get; set; }
diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
index 15f60d831..2c2f22e86 100644
--- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
+++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
@@ -47,6 +47,7 @@ namespace MediaBrowser.Model.LiveTv
public bool ImportFavoritesOnly { get; set; }
public bool AllowHWTranscoding { get; set; }
public bool EnableStreamLooping { get; set; }
+ public bool EnableMpDecimate { get; set; }
public bool EnableNewHdhrChannelIds { get; set; }
public string Source { get; set; }
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index 45e10a76e..cfe20c741 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -191,6 +191,8 @@ namespace MediaBrowser.Providers.TV
});
}
+ private const double UnairedEpisodeThresholdDays = 2;
+
/// <summary>
/// Adds the missing episodes.
/// </summary>
@@ -248,8 +250,7 @@ namespace MediaBrowser.Providers.TV
var targetSeries = DetermineAppropriateSeries(series, tuple.Item1);
- var unairedThresholdDays = 2;
- now = now.AddDays(0 - unairedThresholdDays);
+ now = now.AddDays(0 - UnairedEpisodeThresholdDays);
if (airDate.Value < now)
{
@@ -329,9 +330,13 @@ namespace MediaBrowser.Providers.TV
return true;
}
- if (!allowMissingEpisodes && i.Episode.IsMissingEpisode && !i.Episode.IsUnaired)
+ if (!allowMissingEpisodes && i.Episode.IsMissingEpisode)
{
- return true;
+ // If it's missing, but not unaired, remove it
+ if (!i.Episode.PremiereDate.HasValue || i.Episode.PremiereDate.Value.ToLocalTime().Date.AddDays(UnairedEpisodeThresholdDays) < DateTime.Now.Date)
+ {
+ return true;
+ }
}
return false;
diff --git a/MediaBrowser.Server.Mac.sln b/MediaBrowser.Server.Mac.sln
index ba912566a..051ea660b 100644
--- a/MediaBrowser.Server.Mac.sln
+++ b/MediaBrowser.Server.Mac.sln
@@ -17,8 +17,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model", "Media
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Providers", "MediaBrowser.Providers\MediaBrowser.Providers.csproj", "{442B5058-DCAF-4263-BB6A-F21E31120A1B}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Implementations", "MediaBrowser.Server.Implementations\MediaBrowser.Server.Implementations.csproj", "{2E781478-814D-4A48-9D80-BFF206441A65}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.WebDashboard", "MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj", "{5624B7B5-B5A7-41D8-9F10-CC5611109619}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.XbmcMetadata", "MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj", "{23499896-B135-4527-8574-C26E926EA99E}"
@@ -41,8 +39,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RSSDP", "RSSDP\RSSDP.csproj
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing.Skia", "Emby.Drawing.Skia\Emby.Drawing.Skia.csproj", "{2312DA6D-FF86-4597-9777-BCEEC32D96DD}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Common.Implementations", "Emby.Common.Implementations\Emby.Common.Implementations.csproj", "{1E37A338-9F57-4B70-BD6D-BB9C591E319B}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SocketHttpListener", "SocketHttpListener\SocketHttpListener.csproj", "{1D74413B-E7CF-455B-B021-F52BDF881542}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Nat", "Mono.Nat\Mono.Nat.csproj", "{CB7F2326-6497-4A3D-BA03-48513B17A7BE}"
@@ -210,26 +206,6 @@ Global
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|Any CPU.Build.0 = Release Mono|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|x86.ActiveCfg = Release Mono|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|x86.Build.0 = Release Mono|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|Any CPU.Build.0 = Release|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|x86.ActiveCfg = Release Mono|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|x86.Build.0 = Release Mono|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.ActiveCfg = Debug|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.Build.0 = Debug|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|x86.Build.0 = Release Mono|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.Build.0 = Release|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.ActiveCfg = Release|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.Build.0 = Release|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|Any CPU.ActiveCfg = Release Mono|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|Any CPU.Build.0 = Release Mono|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|x86.ActiveCfg = Release Mono|Any CPU
- {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|x86.Build.0 = Release Mono|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|Any CPU.Build.0 = Release|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|x86.ActiveCfg = Release Mono|Any CPU
@@ -470,50 +446,6 @@ Global
{2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x64.Build.0 = Release|Any CPU
{2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x86.ActiveCfg = Release|Any CPU
{2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x86.Build.0 = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.AppStore|Any CPU.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.AppStore|x86.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.AppStore|x86.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|x86.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|x86.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Any CPU.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|x86.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|x86.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Any CPU.Build.0 = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|x86.ActiveCfg = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|x86.Build.0 = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Any CPU.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Any CPU.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|x86.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|x86.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Win32.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|Win32.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|x64.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Debug|x64.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Mixed Platforms.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Win32.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|Win32.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|x64.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release Mono|x64.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Win32.ActiveCfg = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|Win32.Build.0 = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|x64.ActiveCfg = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Release|x64.Build.0 = Release|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Mixed Platforms.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Mixed Platforms.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Win32.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|Win32.Build.0 = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|x64.ActiveCfg = Debug|Any CPU
- {1E37A338-9F57-4B70-BD6D-BB9C591E319B}.Signed|x64.Build.0 = Debug|Any CPU
{1D74413B-E7CF-455B-B021-F52BDF881542}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{1D74413B-E7CF-455B-B021-F52BDF881542}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{1D74413B-E7CF-455B-B021-F52BDF881542}.AppStore|x86.ActiveCfg = Debug|Any CPU
diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
index 161a4076a..fe9ab13fa 100644
--- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
+++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj
@@ -92,10 +92,6 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll</HintPath>
</Reference>
- <Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
- <HintPath>..\packages\NLog.4.4.12\lib\net45\NLog.dll</HintPath>
- <Private>True</Private>
- </Reference>
<Reference Include="ServiceStack.Text, Version=4.5.8.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll</HintPath>
<Private>True</Private>
diff --git a/MediaBrowser.Server.Mac/MacAppHost.cs b/MediaBrowser.Server.Mac/MacAppHost.cs
index 2f8ee983c..7ad96d2bf 100644
--- a/MediaBrowser.Server.Mac/MacAppHost.cs
+++ b/MediaBrowser.Server.Mac/MacAppHost.cs
@@ -19,11 +19,11 @@ namespace MediaBrowser.Server.Mac
{
public class MacAppHost : ApplicationHost
{
- public MacAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action<string, string, string> certificateGenerator, Func<string> defaultUsernameFactory) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory)
+ public MacAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, networkManager)
{
}
- public override bool CanSelfRestart
+ public override bool CanSelfRestart
{
get
{
diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs
index cedeeb22e..3863937f8 100644
--- a/MediaBrowser.Server.Mac/Main.cs
+++ b/MediaBrowser.Server.Mac/Main.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Model.Logging;
-using MediaBrowser.Server.Implementations;
using System;
using System.Diagnostics;
using System.Globalization;
@@ -20,21 +19,18 @@ using MonoMac.ObjCRuntime;
using Emby.Server.Core;
using Emby.Server.Core.Cryptography;
using Emby.Server.Implementations;
-using Emby.Common.Implementations.Logging;
using Emby.Server.Implementations.Logging;
-using Emby.Common.Implementations.EnvironmentInfo;
using Emby.Server.Mac.Native;
using Emby.Server.Implementations.IO;
-using Emby.Common.Implementations.Networking;
-using Emby.Common.Implementations.Cryptography;
using Mono.Unix.Native;
using MediaBrowser.Model.System;
using MediaBrowser.Model.IO;
-using Emby.Server.Implementations.Logging;
using Emby.Drawing;
using Emby.Drawing.Skia;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Model.Drawing;
+using Emby.Server.Implementations.EnvironmentInfo;
+using Emby.Server.Implementations.Networking;
namespace MediaBrowser.Server.Mac
{
@@ -60,7 +56,7 @@ namespace MediaBrowser.Server.Mac
var appPaths = CreateApplicationPaths(appFolderPath, customProgramDataPath);
- var logManager = new NlogManager(appPaths.LogDirectoryPath, "server");
+ var logManager = new SimpleLogManager(appPaths.LogDirectoryPath, "server");
logManager.ReloadLogger(LogSeverity.Info);
logManager.AddConsoleOutput();
@@ -90,9 +86,7 @@ namespace MediaBrowser.Server.Mac
// Within the mac bundle, go uo two levels then down into Resources folder
var resourcesPath = Path.Combine(Path.GetDirectoryName(appFolderPath), "Resources");
- Action<string> createDirectoryFn = (string obj) => Directory.CreateDirectory(obj);
-
- return new ServerApplicationPaths(programDataPath, appFolderPath, resourcesPath, createDirectoryFn);
+ return new ServerApplicationPaths(programDataPath, appFolderPath, resourcesPath);
}
/// <summary>
@@ -125,10 +119,7 @@ namespace MediaBrowser.Server.Mac
environmentInfo,
imageEncoder,
new SystemEvents(logManager.GetLogger("SystemEvents")),
- new MemoryStreamProvider(),
- new NetworkManager(logManager.GetLogger("NetworkManager")),
- GenerateCertificate,
- () => Environment.UserName);
+ new NetworkManager(logManager.GetLogger("NetworkManager")));
if (options.ContainsOption("-v")) {
Console.WriteLine (AppHost.ApplicationVersion.ToString());
@@ -152,16 +143,11 @@ namespace MediaBrowser.Server.Mac
}
}
- private static void GenerateCertificate(string certPath, string certHost, string certPassword)
- {
- CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, certPassword, _logger);
- }
-
private static EnvironmentInfo GetEnvironmentInfo()
{
var info = new EnvironmentInfo()
{
- CustomOperatingSystem = MediaBrowser.Model.System.OperatingSystem.OSX
+ OperatingSystem = MediaBrowser.Model.System.OperatingSystem.OSX
};
var uname = GetUnixName();
@@ -186,23 +172,23 @@ namespace MediaBrowser.Server.Mac
if (archX86.IsMatch(uname.machine))
{
- info.CustomArchitecture = Architecture.X86;
+ info.SystemArchitecture = Architecture.X86;
}
else if (string.Equals(uname.machine, "x86_64", StringComparison.OrdinalIgnoreCase))
{
- info.CustomArchitecture = Architecture.X64;
+ info.SystemArchitecture = Architecture.X64;
}
else if (uname.machine.StartsWith("arm", StringComparison.OrdinalIgnoreCase))
{
- info.CustomArchitecture = Architecture.Arm;
+ info.SystemArchitecture = Architecture.Arm;
}
else if (System.Environment.Is64BitOperatingSystem)
{
- info.CustomArchitecture = Architecture.X64;
+ info.SystemArchitecture = Architecture.X64;
}
else
{
- info.CustomArchitecture = Architecture.X86;
+ info.SystemArchitecture = Architecture.X86;
}
return info;
diff --git a/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs b/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs
index 7aeff5ac8..1fd140fb9 100644
--- a/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs
+++ b/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs
@@ -1,4 +1,4 @@
-using Emby.Common.Implementations.IO;
+using Emby.Server.Implementations.IO;
using MediaBrowser.Model.Logging;
using Mono.Unix.Native;
using MediaBrowser.Model.System;
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index e4eff4888..eb8a55b4c 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
- <version>3.0.736</version>
+ <version>3.0.740</version>
<title>Emby.Common</title>
<authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index f153d3e6b..5c16159c7 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
- <version>3.0.736</version>
+ <version>3.0.740</version>
<title>Emby.Server.Core</title>
<authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Emby Server.</description>
<copyright>Copyright © Emby 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.736" />
+ <dependency id="MediaBrowser.Common" version="3.0.740" />
</dependencies>
</metadata>
<files>
diff --git a/SharedVersion.cs b/SharedVersion.cs
index fba02a2b0..8a24a887f 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,3 +1,3 @@
using System.Reflection;
-[assembly: AssemblyVersion("3.2.28.3")]
+[assembly: AssemblyVersion("3.2.28.4")]