Merge pull request #2839 from MediaBrowser/dev

Dev
This commit is contained in:
Luke 2017-08-23 16:13:36 -04:00 committed by GitHub
commit 2bd37fd2c2
39 changed files with 437 additions and 473 deletions

View file

@ -508,23 +508,6 @@ namespace Emby.Dlna.ContentDirectory
if (stubType.HasValue) 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; var person = item as Person;
if (person != null) if (person != null)
{ {
@ -1356,7 +1339,6 @@ namespace Emby.Dlna.ContentDirectory
public enum StubType public enum StubType
{ {
Folder = 0, Folder = 0,
People = 1,
Latest = 2, Latest = 2,
Playlists = 3, Playlists = 3,
Albums = 4, Albums = 4,

View file

@ -236,7 +236,7 @@ namespace Emby.Dlna.Didl
AddVideoResource(writer, video, deviceId, filter, contentFeature, streamInfo); 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) .Where(subtitle => subtitle.DeliveryMethod == SubtitleDeliveryMethod.External)
.ToList(); .ToList();
@ -391,14 +391,6 @@ namespace Emby.Dlna.Didl
private string GetDisplayName(BaseItem item, StubType? itemStubType, BaseItem context) 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) if (itemStubType.HasValue && itemStubType.Value == StubType.Latest)
{ {
return _localization.GetLocalizedString("ViewTypeMusicLatest"); return _localization.GetLocalizedString("ViewTypeMusicLatest");
@ -961,12 +953,6 @@ namespace Emby.Dlna.Didl
private void AddCover(BaseItem item, BaseItem context, StubType? stubType, XmlWriter writer) 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; ImageDownloadInfo imageInfo = null;
if (context is UserView) if (context is UserView)

View file

@ -115,14 +115,10 @@ namespace Emby.Server.Implementations.Dto
var programTuples = new List<Tuple<BaseItem, BaseItemDto>>(); var programTuples = new List<Tuple<BaseItem, BaseItemDto>>();
var channelTuples = new List<Tuple<BaseItemDto, LiveTvChannel>>(); var channelTuples = new List<Tuple<BaseItemDto, LiveTvChannel>>();
var refreshQueue = options.Fields.Contains(ItemFields.RefreshState)
? _providerManager.GetRefreshQueue()
: null;
var index = 0; var index = 0;
foreach (var item in items) 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; var tvChannel = item as LiveTvChannel;
if (tvChannel != null) if (tvChannel != null)
@ -176,11 +172,7 @@ namespace Emby.Server.Implementations.Dto
{ {
var syncDictionary = GetSyncedItemProgress(options); var syncDictionary = GetSyncedItemProgress(options);
var refreshQueue = options.Fields.Contains(ItemFields.RefreshState) var dto = GetBaseItemDtoInternal(item, options, user, owner);
? _providerManager.GetRefreshQueue()
: null;
var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user, owner);
var tvChannel = item as LiveTvChannel; var tvChannel = item as LiveTvChannel;
if (tvChannel != null) 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; var fields = options.Fields;
@ -377,6 +369,8 @@ namespace Emby.Server.Implementations.Dto
{ {
dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user); dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true, user);
} }
NormalizeMediaSourceContainers(dto);
} }
} }
@ -412,25 +406,72 @@ namespace Emby.Server.Implementations.Dto
dto.Etag = item.GetEtag(user); dto.Etag = item.GetEtag(user);
} }
if (currentRefreshQueue != null) var liveTvManager = _livetvManager();
{
//dto.RefreshState = item.GetRefreshState(currentRefreshQueue);
}
if (item is ILiveTvRecording) if (item is ILiveTvRecording)
{ {
_livetvManager().AddInfoToRecordingDto(item, dto, user); liveTvManager.AddInfoToRecordingDto(item, dto, user);
}
else
{
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; 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) public BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, Dictionary<string, SyncedItemProgress> syncProgress, User user = null)
{ {
var refreshQueue = options.Fields.Contains(ItemFields.RefreshState) var dto = GetBaseItemDtoInternal(item, options, user);
? _providerManager.GetRefreshQueue()
: null;
var dto = GetBaseItemDtoInternal(item, options, refreshQueue, user);
if (taggedItems != null && options.Fields.Contains(ItemFields.ItemCounts)) if (taggedItems != null && options.Fields.Contains(ItemFields.ItemCounts))
{ {

View file

@ -698,7 +698,6 @@
<EmbeddedResource Include="Localization\Core\ar.json" /> <EmbeddedResource Include="Localization\Core\ar.json" />
<EmbeddedResource Include="Localization\Core\bg-BG.json" /> <EmbeddedResource Include="Localization\Core\bg-BG.json" />
<EmbeddedResource Include="Localization\Core\ca.json" /> <EmbeddedResource Include="Localization\Core\ca.json" />
<EmbeddedResource Include="Localization\Core\core.json" />
<EmbeddedResource Include="Localization\Core\cs.json" /> <EmbeddedResource Include="Localization\Core\cs.json" />
<EmbeddedResource Include="Localization\Core\da.json" /> <EmbeddedResource Include="Localization\Core\da.json" />
<EmbeddedResource Include="Localization\Core\de.json" /> <EmbeddedResource Include="Localization\Core\de.json" />

View file

@ -85,6 +85,8 @@ namespace Emby.Server.Implementations.IO
public bool IsPathLocked(string path) public bool IsPathLocked(string path)
{ {
// This method is not used by the core but it used by auto-organize
var lockedPaths = _tempIgnoredPaths.Keys.ToList(); var lockedPaths = _tempIgnoredPaths.Keys.ToList();
return lockedPaths.Any(i => _fileSystem.AreEqual(i, path) || _fileSystem.ContainsSubPath(i, path)); return lockedPaths.Any(i => _fileSystem.AreEqual(i, path) || _fileSystem.ContainsSubPath(i, path));
} }

View file

@ -1,6 +1,8 @@
using MediaBrowser.Controller.Configuration; using System.Globalization;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Naming.Common; using MediaBrowser.Naming.Common;
using MediaBrowser.Naming.TV; using MediaBrowser.Naming.TV;
@ -17,15 +19,18 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private readonly ILocalizationManager _localization;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SeasonResolver"/> class. /// Initializes a new instance of the <see cref="SeasonResolver"/> class.
/// </summary> /// </summary>
/// <param name="config">The config.</param> /// <param name="config">The config.</param>
public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager) public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization)
{ {
_config = config; _config = config;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_localization = localization;
} }
/// <summary> /// <summary>
@ -47,9 +52,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
SeriesName = series.Name 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; return season;

View file

@ -830,6 +830,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
existingTimer.IsKids = updatedTimer.IsKids; existingTimer.IsKids = updatedTimer.IsKids;
existingTimer.IsNews = updatedTimer.IsNews; existingTimer.IsNews = updatedTimer.IsNews;
existingTimer.IsMovie = updatedTimer.IsMovie; existingTimer.IsMovie = updatedTimer.IsMovie;
existingTimer.IsSeries = updatedTimer.IsSeries;
existingTimer.IsLive = updatedTimer.IsLive;
existingTimer.IsPremiere = updatedTimer.IsPremiere;
existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries; existingTimer.IsProgramSeries = updatedTimer.IsProgramSeries;
existingTimer.IsRepeat = updatedTimer.IsRepeat; existingTimer.IsRepeat = updatedTimer.IsRepeat;
existingTimer.IsSports = updatedTimer.IsSports; existingTimer.IsSports = updatedTimer.IsSports;
@ -861,7 +864,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
public async Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken) 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) public string GetActiveRecordingPath(string id)
@ -875,6 +879,28 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return null; 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) private RecordingInfo GetRecordingInfo(ActiveRecordingInfo info)
{ {
var timer = info.Timer; var timer = info.Timer;
@ -1245,6 +1271,33 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
throw new FileNotFoundException(); 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) public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
{ {
// Ignore the consumer id // Ignore the consumer id
@ -1327,7 +1380,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var activeRecordingInfo = new ActiveRecordingInfo var activeRecordingInfo = new ActiveRecordingInfo
{ {
CancellationTokenSource = new CancellationTokenSource(), CancellationTokenSource = new CancellationTokenSource(),
Timer = timer Timer = timer,
Id = timer.Id
}; };
if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo)) if (_activeRecordings.TryAdd(timer.Id, activeRecordingInfo))
@ -1493,7 +1547,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath); recordPath = recorder.GetOutputPath(mediaStreamInfo, recordPath);
recordPath = EnsureFileUnique(recordPath, timer.Id); recordPath = EnsureFileUnique(recordPath, timer.Id);
_libraryManager.RegisterIgnoredPath(recordPath);
_libraryMonitor.ReportFileSystemChangeBeginning(recordPath); _libraryMonitor.ReportFileSystemChangeBeginning(recordPath);
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath));
activeRecordingInfo.Path = recordPath; activeRecordingInfo.Path = recordPath;
@ -1512,6 +1565,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
_timerProvider.AddOrUpdate(timer, false); _timerProvider.AddOrUpdate(timer, false);
SaveRecordingMetadata(timer, recordPath, seriesPath); SaveRecordingMetadata(timer, recordPath, seriesPath);
TriggerRefresh(recordPath);
EnforceKeepUpTo(timer, seriesPath); EnforceKeepUpTo(timer, seriesPath);
}; };
@ -1543,7 +1597,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
} }
} }
_libraryManager.UnRegisterIgnoredPath(recordPath); TriggerRefresh(recordPath);
_libraryMonitor.ReportFileSystemChangeComplete(recordPath, true); _libraryMonitor.ReportFileSystemChangeComplete(recordPath, true);
ActiveRecordingInfo removed; ActiveRecordingInfo removed;
@ -1574,6 +1628,44 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
OnRecordingStatusChanged(); 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() private void OnRecordingStatusChanged()
{ {
EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs
@ -2621,14 +2713,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return list; 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; private const int TunerDiscoveryDurationMs = 3000;
public async Task<List<TunerHostInfo>> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken) public async Task<List<TunerHostInfo>> DiscoverTuners(bool newDevicesOnly, CancellationToken cancellationToken)

View file

@ -58,6 +58,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
timerInfo.OriginalAirDate = programInfo.OriginalAirDate; timerInfo.OriginalAirDate = programInfo.OriginalAirDate;
timerInfo.IsProgramSeries = programInfo.IsSeries; timerInfo.IsProgramSeries = programInfo.IsSeries;
timerInfo.IsSeries = programInfo.IsSeries;
timerInfo.IsLive = programInfo.IsLive;
timerInfo.IsPremiere = programInfo.IsPremiere;
timerInfo.HomePageUrl = programInfo.HomePageUrl; timerInfo.HomePageUrl = programInfo.HomePageUrl;
timerInfo.CommunityRating = programInfo.CommunityRating; timerInfo.CommunityRating = programInfo.CommunityRating;
timerInfo.Overview = programInfo.Overview; timerInfo.Overview = programInfo.Overview;

View file

@ -247,7 +247,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings
ProgramAudio audioType = ProgramAudio.Stereo; ProgramAudio audioType = ProgramAudio.Stereo;
bool repeat = programInfo.@new == null; 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) if (programInfo.audioProperties != null)
{ {
@ -300,7 +303,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
Etag = programInfo.md5 Etag = programInfo.md5
}; };
var showId = programInfo.programID ?? string.Empty; var showId = programId;
if (!info.IsSeries) if (!info.IsSeries)
{ {
@ -339,11 +342,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings
if (details.descriptions != null) 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; 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; info.Overview = details.descriptions.description100[0].description;
} }
@ -351,16 +354,19 @@ namespace Emby.Server.Implementations.LiveTv.Listings
if (info.IsSeries) if (info.IsSeries)
{ {
info.SeriesId = programInfo.programID.Substring(0, 10); info.SeriesId = programId.Substring(0, 10);
if (details.metadata != null) if (details.metadata != null)
{ {
var gracenote = details.metadata.Find(x => x.Gracenote != null).Gracenote; var gracenote = details.metadata.Find(x => x.Gracenote != null).Gracenote;
info.SeasonNumber = gracenote.season; if (gracenote != null)
if (gracenote.episode > 0)
{ {
info.EpisodeNumber = gracenote.episode; info.SeasonNumber = gracenote.season;
if (gracenote.episode > 0)
{
info.EpisodeNumber = gracenote.episode;
}
} }
} }
} }

View file

@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.LiveTv
private readonly LiveTvDtoService _tvDtoService; 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); private readonly SemaphoreSlim _refreshRecordingsLock = new SemaphoreSlim(1, 1);
@ -124,7 +124,7 @@ namespace Emby.Server.Implementations.LiveTv
/// <param name="listingProviders">The listing providers.</param> /// <param name="listingProviders">The listing providers.</param>
public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders) public void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders)
{ {
_services.AddRange(services); _services = services.ToArray();
_tunerHosts.AddRange(tunerHosts); _tunerHosts.AddRange(tunerHosts);
_listingProviders.AddRange(listingProviders); _listingProviders.AddRange(listingProviders);
@ -1221,9 +1221,9 @@ namespace Emby.Server.Implementations.LiveTv
await EmbyTV.EmbyTV.Current.ScanForTunerDeviceChanges(cancellationToken).ConfigureAwait(false); await EmbyTV.EmbyTV.Current.ScanForTunerDeviceChanges(cancellationToken).ConfigureAwait(false);
var numComplete = 0; var numComplete = 0;
double progressPerService = _services.Count == 0 double progressPerService = _services.Length == 0
? 0 ? 0
: 1 / _services.Count; : 1 / _services.Length;
var newChannelIdList = new List<Guid>(); var newChannelIdList = new List<Guid>();
var newProgramIdList = new List<Guid>(); var newProgramIdList = new List<Guid>();
@ -1255,7 +1255,7 @@ namespace Emby.Server.Implementations.LiveTv
numComplete++; numComplete++;
double percent = numComplete; double percent = numComplete;
percent /= _services.Count; percent /= _services.Length;
progress.Report(100 * percent); progress.Report(100 * percent);
} }
@ -1561,11 +1561,6 @@ namespace Emby.Server.Implementations.LiveTv
return new QueryResult<BaseItem>(); return new QueryResult<BaseItem>();
} }
if ((query.IsInProgress ?? false))
{
return new QueryResult<BaseItem>();
}
var folderIds = EmbyTV.EmbyTV.Current.GetRecordingFolders() var folderIds = EmbyTV.EmbyTV.Current.GetRecordingFolders()
.SelectMany(i => i.Locations) .SelectMany(i => i.Locations)
.Distinct(StringComparer.OrdinalIgnoreCase) .Distinct(StringComparer.OrdinalIgnoreCase)
@ -1577,13 +1572,10 @@ namespace Emby.Server.Implementations.LiveTv
var excludeItemTypes = new List<string>(); var excludeItemTypes = new List<string>();
if (!query.IsInProgress.HasValue) folderIds.Add(internalLiveTvFolderId);
{
folderIds.Add(internalLiveTvFolderId);
excludeItemTypes.Add(typeof(LiveTvChannel).Name); excludeItemTypes.Add(typeof(LiveTvChannel).Name);
excludeItemTypes.Add(typeof(LiveTvProgram).Name); excludeItemTypes.Add(typeof(LiveTvProgram).Name);
}
if (folderIds.Count == 0) 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) return _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{ {
MediaTypes = new[] { MediaType.Video }, MediaTypes = new[] { MediaType.Video },
@ -1659,11 +1664,6 @@ namespace Emby.Server.Implementations.LiveTv
return new QueryResult<BaseItemDto>(); return new QueryResult<BaseItemDto>();
} }
if (_services.Count > 1)
{
return new QueryResult<BaseItemDto>();
}
if (user == null || (query.IsInProgress ?? false)) if (user == null || (query.IsInProgress ?? false))
{ {
return new QueryResult<BaseItemDto>(); return new QueryResult<BaseItemDto>();
@ -1722,13 +1722,9 @@ namespace Emby.Server.Implementations.LiveTv
var folder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false); 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); return GetEmbyRecordings(query, options, folder.Id, user);
} }
@ -1920,6 +1916,11 @@ namespace Emby.Server.Implementations.LiveTv
await AddRecordingInfo(programTuples, CancellationToken.None).ConfigureAwait(false); 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) public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, User user = null)
{ {
var recording = (ILiveTvRecording)item; var recording = (ILiveTvRecording)item;
@ -1949,20 +1950,6 @@ namespace Emby.Server.Implementations.LiveTv
dto.IsKids = info.IsKids; dto.IsKids = info.IsKids;
dto.IsPremiere = info.IsPremiere; dto.IsPremiere = info.IsPremiere;
dto.CanDelete = user == null
? recording.CanDelete()
: recording.CanDelete(user);
if (dto.MediaSources == null)
{
dto.MediaSources = recording.GetMediaSources(true);
}
if (dto.MediaStreams == null)
{
dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToArray();
}
if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue) if (info.Status == RecordingStatus.InProgress && info.EndDate.HasValue)
{ {
var now = DateTime.UtcNow.Ticks; var now = DateTime.UtcNow.Ticks;
@ -1986,6 +1973,65 @@ namespace Emby.Server.Implementations.LiveTv
} }
} }
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 = startDate.Ticks;
var end = endDate.Ticks;
var pct = now - start;
pct /= end;
pct *= 100;
dto.CompletionPercentage = pct;
}
if (channel != null)
{
dto.ChannelName = channel.Name;
if (channel.HasImage(ImageType.Primary))
{
dto.ChannelPrimaryImageTag = _tvDtoService.GetImageTag(channel);
}
}
}
public async Task<QueryResult<BaseItemDto>> GetRecordings(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken) public async Task<QueryResult<BaseItemDto>> GetRecordings(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken)
{ {
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
@ -2098,7 +2144,6 @@ namespace Emby.Server.Implementations.LiveTv
if (service is EmbyTV.EmbyTV) 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); return service.DeleteRecordingAsync(GetItemExternalId(recording), CancellationToken.None);
} }
@ -2348,7 +2393,6 @@ namespace Emby.Server.Implementations.LiveTv
var currentChannelsDict = new Dictionary<string, BaseItemDto>(); var currentChannelsDict = new Dictionary<string, BaseItemDto>();
var addCurrentProgram = options.AddCurrentProgram; var addCurrentProgram = options.AddCurrentProgram;
var addMediaSources = options.Fields.Contains(ItemFields.MediaSources);
var addServiceName = options.Fields.Contains(ItemFields.ServiceName); var addServiceName = options.Fields.Contains(ItemFields.ServiceName);
foreach (var tuple in tuples) foreach (var tuple in tuples)
@ -2367,11 +2411,6 @@ namespace Emby.Server.Implementations.LiveTv
currentChannelsDict[dto.Id] = dto; currentChannelsDict[dto.Id] = dto;
if (addMediaSources)
{
dto.MediaSources = channel.GetMediaSources(true);
}
if (addCurrentProgram) if (addCurrentProgram)
{ {
var channelIdString = channel.Id.ToString("N"); var channelIdString = channel.Id.ToString("N");

View file

@ -43,9 +43,11 @@ namespace Emby.Server.Implementations.LiveTv
if (baseItem.SourceType == SourceType.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 char StreamIdDelimeter = '_';
private const string StreamIdDelimeterString = "_"; 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; IEnumerable<MediaSourceInfo> sources;
@ -67,12 +69,20 @@ namespace Emby.Server.Implementations.LiveTv
if (item is ILiveTvRecording) if (item is ILiveTvRecording)
{ {
sources = await _liveTvManager.GetRecordingMediaSources(item, cancellationToken) sources = await _liveTvManager.GetRecordingMediaSources(item, cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
else else
{ {
sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken) if (activeRecordingInfo != null)
.ConfigureAwait(false); {
sources = await EmbyTV.EmbyTV.Current.GetRecordingStreamMediaSources(activeRecordingInfo, cancellationToken)
.ConfigureAwait(false);
}
else
{
sources = await _liveTvManager.GetChannelMediaSources(item, cancellationToken)
.ConfigureAwait(false);
}
} }
} }
catch (NotImplementedException) catch (NotImplementedException)

View file

@ -165,6 +165,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
RequiresOpening = true, RequiresOpening = true,
RequiresClosing = true, RequiresClosing = true,
RequiresLooping = info.EnableStreamLooping, RequiresLooping = info.EnableStreamLooping,
EnableMpDecimate = info.EnableMpDecimate,
ReadAtNativeFramerate = false, ReadAtNativeFramerate = false,

View file

@ -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."
}

View file

@ -1,5 +1,4 @@
{ {
"DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.",
"AppDeviceValues": "App: {0}, Device: {1}", "AppDeviceValues": "App: {0}, Device: {1}",
"UserDownloadingItemWithValues": "{0} is downloading {1}", "UserDownloadingItemWithValues": "{0} is downloading {1}",
"FolderTypeMixed": "Mixed content", "FolderTypeMixed": "Mixed content",
@ -13,15 +12,12 @@
"FolderTypeBooks": "Books", "FolderTypeBooks": "Books",
"FolderTypeTvShows": "TV", "FolderTypeTvShows": "TV",
"FolderTypeInherit": "Inherit", "FolderTypeInherit": "Inherit",
"HeaderCastCrew": "Cast & Crew",
"HeaderPeople": "People",
"ValueSpecialEpisodeName": "Special - {0}", "ValueSpecialEpisodeName": "Special - {0}",
"LabelChapterName": "Chapter {0}", "LabelChapterName": "Chapter {0}",
"NameSeasonUnknown": "Season Unknown", "NameSeasonUnknown": "Season Unknown",
"NameSeasonNumber": "Season {0}", "NameSeasonNumber": "Season {0}",
"LabelExit": "Exit", "LabelExit": "Exit",
"LabelVisitCommunity": "Visit Community", "LabelVisitCommunity": "Visit Community",
"LabelGithub": "Github",
"LabelApiDocumentation": "Api Documentation", "LabelApiDocumentation": "Api Documentation",
"LabelDeveloperResources": "Developer Resources", "LabelDeveloperResources": "Developer Resources",
"LabelBrowseLibrary": "Browse Library", "LabelBrowseLibrary": "Browse Library",
@ -164,15 +160,5 @@
"HeaderStatus": "Status", "HeaderStatus": "Status",
"HeaderTracks": "Tracks", "HeaderTracks": "Tracks",
"HeaderMusicArtist": "Music artist", "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." "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly."
} }

View file

@ -335,7 +335,7 @@ namespace Emby.Server.Implementations.Localization
const string prefix = "Core"; const string prefix = "Core";
var key = prefix + culture; 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) private Dictionary<string, string> GetDictionary(string prefix, string culture, string baseFilename)

View file

@ -277,15 +277,7 @@ namespace Emby.Server.Implementations.Updates
private TimeSpan GetCacheLength() private TimeSpan GetCacheLength()
{ {
switch (GetSystemUpdateLevel()) return TimeSpan.FromMinutes(3);
{
case PackageVersionClass.Beta:
return TimeSpan.FromMinutes(30);
case PackageVersionClass.Dev:
return TimeSpan.FromMinutes(3);
default:
return TimeSpan.FromHours(24);
}
} }
protected PackageInfo[] FilterPackages(List<PackageInfo> packages) protected PackageInfo[] FilterPackages(List<PackageInfo> packages)

View file

@ -648,15 +648,15 @@ namespace MediaBrowser.Controller.Entities
public static bool IsPathOffline(string path, List<string> allLibraryPaths) public static bool IsPathOffline(string path, List<string> allLibraryPaths)
{ {
if (FileSystem.FileExists(path)) //if (FileSystem.FileExists(path))
{ //{
return false; // return false;
} //}
var originalPath = path; var originalPath = path;
// Depending on whether the path is local or unc, it may return either null or '\' at the top // 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)) if (FileSystem.DirectoryExists(path))
{ {

View file

@ -4,7 +4,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
{ {
public interface IHasMediaSources : IHasUserData public interface IHasMediaSources : IHasMetadata
{ {
/// <summary> /// <summary>
/// Gets the media sources. /// Gets the media sources.

View file

@ -160,7 +160,7 @@ namespace MediaBrowser.Controller.Entities
public string[] GetPlayableStreamFileNames() public string[] GetPlayableStreamFileNames()
{ {
return GetPlayableStreamFiles().Select(System.IO.Path.GetFileName).ToArray(); return GetPlayableStreamFiles().Select(System.IO.Path.GetFileName).ToArray();
} }
/// <summary> /// <summary>
@ -234,6 +234,35 @@ namespace MediaBrowser.Controller.Entities
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video))); return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
} }
[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] [IgnoreDataMember]
protected virtual bool EnableDefaultVideoUserDataKeys protected virtual bool EnableDefaultVideoUserDataKeys
{ {
@ -616,6 +645,14 @@ namespace MediaBrowser.Controller.Entities
var list = GetAllVideosForMediaSources(); var list = GetAllVideosForMediaSources();
var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList(); 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 => return result.OrderBy(i =>
{ {
if (i.VideoType == VideoType.VideoFile) if (i.VideoType == VideoType.VideoFile)

View file

@ -384,5 +384,9 @@ namespace MediaBrowser.Controller.LiveTv
string GetEmbyTvActiveRecordingPath(string id); string GetEmbyTvActiveRecordingPath(string id);
Task<LiveStream> GetEmbyTvLiveStream(string id); Task<LiveStream> GetEmbyTvLiveStream(string id);
ActiveRecordingInfo GetActiveRecordingInfo(string path);
void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, ActiveRecordingInfo activeRecordingInfo, User user = null);
} }
} }

View file

@ -36,4 +36,13 @@ namespace MediaBrowser.Controller.LiveTv
DateTime? EndDate { get; set; } DateTime? EndDate { get; set; }
DateTime DateCreated { 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; }
}
} }

View file

@ -109,6 +109,9 @@ namespace MediaBrowser.Controller.LiveTv
public bool IsKids { get; set; } public bool IsKids { get; set; }
public bool IsSports { get; set; } public bool IsSports { get; set; }
public bool IsNews { 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 int? ProductionYear { get; set; }
public string EpisodeTitle { get; set; } public string EpisodeTitle { get; set; }
public DateTime? OriginalAirDate { get; set; } public DateTime? OriginalAirDate { get; set; }

View file

@ -778,6 +778,11 @@ namespace MediaBrowser.Controller.MediaEncoding
return false; return false;
} }
if (state.EnableMpDecimate)
{
return false;
}
if (videoStream.IsInterlaced) if (videoStream.IsInterlaced)
{ {
if (request.DeInterlace) 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) if (filters.Count > 0)
{ {
output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray())); output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray()));

View file

@ -127,6 +127,11 @@ namespace MediaBrowser.Controller.MediaEncoding
} }
} }
public bool EnableMpDecimate
{
get { return MediaSource.EnableMpDecimate; }
}
public string AlbumCoverPath { get; set; } public string AlbumCoverPath { get; set; }
public string InputAudioSync { get; set; } public string InputAudioSync { get; set; }

View file

@ -14,6 +14,7 @@ namespace MediaBrowser.Model.Configuration
public int H264Crf { get; set; } public int H264Crf { get; set; }
public string H264Preset { get; set; } public string H264Preset { get; set; }
public bool EnableHardwareEncoding { get; set; } public bool EnableHardwareEncoding { get; set; }
public bool EnableSubtitleExtraction { get; set; }
public string[] HardwareDecodingCodecs { get; set; } public string[] HardwareDecodingCodecs { get; set; }
@ -26,7 +27,7 @@ namespace MediaBrowser.Model.Configuration
VaapiDevice = "/dev/dri/card0"; VaapiDevice = "/dev/dri/card0";
H264Crf = 23; H264Crf = 23;
EnableHardwareEncoding = true; EnableHardwareEncoding = true;
EnableSubtitleExtraction = true;
HardwareDecodingCodecs = new string[] { "h264", "vc1" }; HardwareDecodingCodecs = new string[] { "h264", "vc1" };
} }
} }

View file

@ -4,6 +4,7 @@
{ {
bool CanEncodeToAudioCodec(string codec); bool CanEncodeToAudioCodec(string codec);
bool CanEncodeToSubtitleCodec(string codec); bool CanEncodeToSubtitleCodec(string codec);
bool CanExtractSubtitles(string codec);
} }
public class FullTranscoderSupport : ITranscoderSupport public class FullTranscoderSupport : ITranscoderSupport
@ -16,5 +17,9 @@
{ {
return true; return true;
} }
public bool CanExtractSubtitles(string codec)
{
return true;
}
} }
} }

View file

@ -686,7 +686,7 @@ namespace MediaBrowser.Model.Dlna
if (subtitleStream != null) 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.SubtitleDeliveryMethod = subtitleProfile.Method;
playlistItem.SubtitleFormat = subtitleProfile.Format; playlistItem.SubtitleFormat = subtitleProfile.Format;
@ -728,7 +728,7 @@ namespace MediaBrowser.Model.Dlna
if (subtitleStream != null) 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.SubtitleDeliveryMethod = subtitleProfile.Method;
playlistItem.SubtitleFormat = subtitleProfile.Format; playlistItem.SubtitleFormat = subtitleProfile.Format;
@ -1183,7 +1183,7 @@ namespace MediaBrowser.Model.Dlna
{ {
if (subtitleStream != null) 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) 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); 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))) 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 // 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, Method = SubtitleDeliveryMethod.Encode,
Format = subtitleStream.Codec Format = subtitleStream.Codec
@ -1291,7 +1293,7 @@ namespace MediaBrowser.Model.Dlna
return false; 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) foreach (SubtitleProfile profile in subtitleProfiles)
{ {
@ -1310,6 +1312,11 @@ namespace MediaBrowser.Model.Dlna
continue; continue;
} }
if (!subtitleStream.IsExternal && !transcoderSupport.CanExtractSubtitles(subtitleStream.Codec))
{
continue;
}
if ((profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format)) || if ((profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format)) ||
(profile.Method == SubtitleDeliveryMethod.Hls && subtitleStream.IsTextSubtitleStream)) (profile.Method == SubtitleDeliveryMethod.Hls && subtitleStream.IsTextSubtitleStream))
{ {

View file

@ -309,14 +309,14 @@ namespace MediaBrowser.Model.Dlna
return list; 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>(); List<SubtitleStreamInfo> newList = new List<SubtitleStreamInfo>();
// First add the selected track // First add the selected track
@ -331,12 +331,12 @@ namespace MediaBrowser.Model.Dlna
return newList; 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>(); List<SubtitleStreamInfo> list = new List<SubtitleStreamInfo>();
@ -352,7 +352,7 @@ namespace MediaBrowser.Model.Dlna
{ {
if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value) 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)) 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; 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) if (enableAllProfiles)
{ {
foreach (SubtitleProfile profile in DeviceProfile.SubtitleProfiles) 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); list.Add(info);
} }
} }
else else
{ {
SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles); SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles, transcoderSupport);
list.Add(info); 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 SubtitleStreamInfo info = new SubtitleStreamInfo
{ {
IsForced = stream.IsForced, IsForced = stream.IsForced,

View file

@ -41,6 +41,7 @@ namespace MediaBrowser.Model.Dto
public string OpenToken { get; set; } public string OpenToken { get; set; }
public bool RequiresClosing { get; set; } public bool RequiresClosing { get; set; }
public bool SupportsProbing { get; set; } public bool SupportsProbing { get; set; }
public bool EnableMpDecimate { get; set; }
public string LiveStreamId { get; set; } public string LiveStreamId { get; set; }
public int? BufferMs { get; set; } public int? BufferMs { get; set; }

View file

@ -47,6 +47,7 @@ namespace MediaBrowser.Model.LiveTv
public bool ImportFavoritesOnly { get; set; } public bool ImportFavoritesOnly { get; set; }
public bool AllowHWTranscoding { get; set; } public bool AllowHWTranscoding { get; set; }
public bool EnableStreamLooping { get; set; } public bool EnableStreamLooping { get; set; }
public bool EnableMpDecimate { get; set; }
public bool EnableNewHdhrChannelIds { get; set; } public bool EnableNewHdhrChannelIds { get; set; }
public string Source { get; set; } public string Source { get; set; }

View file

@ -191,6 +191,8 @@ namespace MediaBrowser.Providers.TV
}); });
} }
private const double UnairedEpisodeThresholdDays = 2;
/// <summary> /// <summary>
/// Adds the missing episodes. /// Adds the missing episodes.
/// </summary> /// </summary>
@ -248,8 +250,7 @@ namespace MediaBrowser.Providers.TV
var targetSeries = DetermineAppropriateSeries(series, tuple.Item1); var targetSeries = DetermineAppropriateSeries(series, tuple.Item1);
var unairedThresholdDays = 2; now = now.AddDays(0 - UnairedEpisodeThresholdDays);
now = now.AddDays(0 - unairedThresholdDays);
if (airDate.Value < now) if (airDate.Value < now)
{ {
@ -329,9 +330,13 @@ namespace MediaBrowser.Providers.TV
return true; 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; return false;

View file

@ -17,8 +17,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model", "Media
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Providers", "MediaBrowser.Providers\MediaBrowser.Providers.csproj", "{442B5058-DCAF-4263-BB6A-F21E31120A1B}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Providers", "MediaBrowser.Providers\MediaBrowser.Providers.csproj", "{442B5058-DCAF-4263-BB6A-F21E31120A1B}"
EndProject 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}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.WebDashboard", "MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj", "{5624B7B5-B5A7-41D8-9F10-CC5611109619}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.XbmcMetadata", "MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj", "{23499896-B135-4527-8574-C26E926EA99E}" 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 EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing.Skia", "Emby.Drawing.Skia\Emby.Drawing.Skia.csproj", "{2312DA6D-FF86-4597-9777-BCEEC32D96DD}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing.Skia", "Emby.Drawing.Skia\Emby.Drawing.Skia.csproj", "{2312DA6D-FF86-4597-9777-BCEEC32D96DD}"
EndProject 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}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SocketHttpListener", "SocketHttpListener\SocketHttpListener.csproj", "{1D74413B-E7CF-455B-B021-F52BDF881542}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Nat", "Mono.Nat\Mono.Nat.csproj", "{CB7F2326-6497-4A3D-BA03-48513B17A7BE}" 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|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.ActiveCfg = Release Mono|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|x86.Build.0 = 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.ActiveCfg = Release|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|Any CPU.Build.0 = 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 {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|x64.Build.0 = Release|Any CPU
{2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Signed|x86.ActiveCfg = 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 {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.ActiveCfg = Debug|Any CPU
{1D74413B-E7CF-455B-B021-F52BDF881542}.AppStore|Any CPU.Build.0 = 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 {1D74413B-E7CF-455B-B021-F52BDF881542}.AppStore|x86.ActiveCfg = Debug|Any CPU

View file

@ -92,10 +92,6 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll</HintPath> <HintPath>..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll</HintPath>
</Reference> </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"> <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> <HintPath>..\packages\ServiceStack.Text.4.5.8\lib\net45\ServiceStack.Text.dll</HintPath>
<Private>True</Private> <Private>True</Private>

View file

@ -19,11 +19,11 @@ namespace MediaBrowser.Server.Mac
{ {
public class MacAppHost : ApplicationHost 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 get
{ {

View file

@ -1,5 +1,4 @@
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
@ -20,21 +19,18 @@ using MonoMac.ObjCRuntime;
using Emby.Server.Core; using Emby.Server.Core;
using Emby.Server.Core.Cryptography; using Emby.Server.Core.Cryptography;
using Emby.Server.Implementations; using Emby.Server.Implementations;
using Emby.Common.Implementations.Logging;
using Emby.Server.Implementations.Logging; using Emby.Server.Implementations.Logging;
using Emby.Common.Implementations.EnvironmentInfo;
using Emby.Server.Mac.Native; using Emby.Server.Mac.Native;
using Emby.Server.Implementations.IO; using Emby.Server.Implementations.IO;
using Emby.Common.Implementations.Networking;
using Emby.Common.Implementations.Cryptography;
using Mono.Unix.Native; using Mono.Unix.Native;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using Emby.Server.Implementations.Logging;
using Emby.Drawing; using Emby.Drawing;
using Emby.Drawing.Skia; using Emby.Drawing.Skia;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Drawing;
using Emby.Server.Implementations.EnvironmentInfo;
using Emby.Server.Implementations.Networking;
namespace MediaBrowser.Server.Mac namespace MediaBrowser.Server.Mac
{ {
@ -60,7 +56,7 @@ namespace MediaBrowser.Server.Mac
var appPaths = CreateApplicationPaths(appFolderPath, customProgramDataPath); var appPaths = CreateApplicationPaths(appFolderPath, customProgramDataPath);
var logManager = new NlogManager(appPaths.LogDirectoryPath, "server"); var logManager = new SimpleLogManager(appPaths.LogDirectoryPath, "server");
logManager.ReloadLogger(LogSeverity.Info); logManager.ReloadLogger(LogSeverity.Info);
logManager.AddConsoleOutput(); logManager.AddConsoleOutput();
@ -90,9 +86,7 @@ namespace MediaBrowser.Server.Mac
// Within the mac bundle, go uo two levels then down into Resources folder // Within the mac bundle, go uo two levels then down into Resources folder
var resourcesPath = Path.Combine(Path.GetDirectoryName(appFolderPath), "Resources"); var resourcesPath = Path.Combine(Path.GetDirectoryName(appFolderPath), "Resources");
Action<string> createDirectoryFn = (string obj) => Directory.CreateDirectory(obj); return new ServerApplicationPaths(programDataPath, appFolderPath, resourcesPath);
return new ServerApplicationPaths(programDataPath, appFolderPath, resourcesPath, createDirectoryFn);
} }
/// <summary> /// <summary>
@ -125,10 +119,7 @@ namespace MediaBrowser.Server.Mac
environmentInfo, environmentInfo,
imageEncoder, imageEncoder,
new SystemEvents(logManager.GetLogger("SystemEvents")), new SystemEvents(logManager.GetLogger("SystemEvents")),
new MemoryStreamProvider(), new NetworkManager(logManager.GetLogger("NetworkManager")));
new NetworkManager(logManager.GetLogger("NetworkManager")),
GenerateCertificate,
() => Environment.UserName);
if (options.ContainsOption("-v")) { if (options.ContainsOption("-v")) {
Console.WriteLine (AppHost.ApplicationVersion.ToString()); 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() private static EnvironmentInfo GetEnvironmentInfo()
{ {
var info = new EnvironmentInfo() var info = new EnvironmentInfo()
{ {
CustomOperatingSystem = MediaBrowser.Model.System.OperatingSystem.OSX OperatingSystem = MediaBrowser.Model.System.OperatingSystem.OSX
}; };
var uname = GetUnixName(); var uname = GetUnixName();
@ -186,23 +172,23 @@ namespace MediaBrowser.Server.Mac
if (archX86.IsMatch(uname.machine)) if (archX86.IsMatch(uname.machine))
{ {
info.CustomArchitecture = Architecture.X86; info.SystemArchitecture = Architecture.X86;
} }
else if (string.Equals(uname.machine, "x86_64", StringComparison.OrdinalIgnoreCase)) 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)) else if (uname.machine.StartsWith("arm", StringComparison.OrdinalIgnoreCase))
{ {
info.CustomArchitecture = Architecture.Arm; info.SystemArchitecture = Architecture.Arm;
} }
else if (System.Environment.Is64BitOperatingSystem) else if (System.Environment.Is64BitOperatingSystem)
{ {
info.CustomArchitecture = Architecture.X64; info.SystemArchitecture = Architecture.X64;
} }
else else
{ {
info.CustomArchitecture = Architecture.X86; info.SystemArchitecture = Architecture.X86;
} }
return info; return info;

View file

@ -1,4 +1,4 @@
using Emby.Common.Implementations.IO; using Emby.Server.Implementations.IO;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using Mono.Unix.Native; using Mono.Unix.Native;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;

View file

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Common</id> <id>MediaBrowser.Common</id>
<version>3.0.736</version> <version>3.0.740</version>
<title>Emby.Common</title> <title>Emby.Common</title>
<authors>Emby Team</authors> <authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>

View file

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata> <metadata>
<id>MediaBrowser.Server.Core</id> <id>MediaBrowser.Server.Core</id>
<version>3.0.736</version> <version>3.0.740</version>
<title>Emby.Server.Core</title> <title>Emby.Server.Core</title>
<authors>Emby Team</authors> <authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners> <owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Emby Server.</description> <description>Contains core components required to build plugins for Emby Server.</description>
<copyright>Copyright © Emby 2013</copyright> <copyright>Copyright © Emby 2013</copyright>
<dependencies> <dependencies>
<dependency id="MediaBrowser.Common" version="3.0.736" /> <dependency id="MediaBrowser.Common" version="3.0.740" />
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>

View file

@ -1,3 +1,3 @@
using System.Reflection; using System.Reflection;
[assembly: AssemblyVersion("3.2.28.3")] [assembly: AssemblyVersion("3.2.28.4")]