mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-04 06:48:35 +01:00
add cinema mode feature
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Dto;
|
||||
@@ -9,7 +10,7 @@ using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public class ChannelVideoItem : Video, IChannelMediaItem
|
||||
public class ChannelVideoItem : Video, IChannelMediaItem, IHasLookupInfo<ChannelItemLookupInfo>
|
||||
{
|
||||
public string ExternalId { get; set; }
|
||||
|
||||
@@ -87,5 +88,14 @@ namespace MediaBrowser.Controller.Channels
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public ChannelItemLookupInfo GetLookupInfo()
|
||||
{
|
||||
var info = GetItemLookupInfo<ChannelItemLookupInfo>();
|
||||
|
||||
info.ContentType = ContentType;
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,14 @@ namespace MediaBrowser.Controller.Channels
|
||||
/// <returns>Task{QueryResult{BaseItemDto}}.</returns>
|
||||
Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all media internal.
|
||||
/// </summary>
|
||||
/// <param name="query">The query.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task<QueryResult<BaseItem>>.</returns>
|
||||
Task<QueryResult<BaseItem>> GetAllMediaInternal(AllChannelMediaQuery query, CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all media.
|
||||
/// </summary>
|
||||
|
||||
@@ -5,8 +5,6 @@ namespace MediaBrowser.Controller.Channels
|
||||
{
|
||||
public interface IChannelMediaItem : IChannelItem
|
||||
{
|
||||
bool IsInfiniteStream { get; set; }
|
||||
|
||||
long? RunTimeTicks { get; set; }
|
||||
string MediaType { get; }
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
||||
public string Container { get; set; }
|
||||
public int? TotalBitrate { get; set; }
|
||||
public List<string> Tags { get; set; }
|
||||
public ExtraType ExtraType { get; set; }
|
||||
|
||||
public bool IsThemeMedia { get; set; }
|
||||
|
||||
|
||||
@@ -41,16 +41,25 @@ namespace MediaBrowser.Controller.Entities
|
||||
/// <summary>
|
||||
/// The supported image extensions
|
||||
/// </summary>
|
||||
public static readonly string[] SupportedImageExtensions = new[] { ".png", ".jpg", ".jpeg", ".tbn" };
|
||||
public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".tbn" };
|
||||
|
||||
/// <summary>
|
||||
/// The trailer folder name
|
||||
/// </summary>
|
||||
public const string TrailerFolderName = "trailers";
|
||||
public const string ThemeSongsFolderName = "theme-music";
|
||||
public const string ThemeSongFilename = "theme";
|
||||
public const string ThemeVideosFolderName = "backdrops";
|
||||
public const string XbmcTrailerFileSuffix = "-trailer";
|
||||
public static string TrailerFolderName = "trailers";
|
||||
public static string ThemeSongsFolderName = "theme-music";
|
||||
public static string ThemeSongFilename = "theme";
|
||||
public static string ThemeVideosFolderName = "backdrops";
|
||||
|
||||
public static List<KeyValuePair<string, ExtraType>> ExtraSuffixes = new List<KeyValuePair<string, ExtraType>>
|
||||
{
|
||||
new KeyValuePair<string,ExtraType>("-trailer", ExtraType.Trailer),
|
||||
new KeyValuePair<string,ExtraType>("-deleted", ExtraType.DeletedScene),
|
||||
new KeyValuePair<string,ExtraType>("-behindthescenes", ExtraType.BehindTheScenes),
|
||||
new KeyValuePair<string,ExtraType>("-interview", ExtraType.Interview),
|
||||
new KeyValuePair<string,ExtraType>("-scene", ExtraType.Scene),
|
||||
new KeyValuePair<string,ExtraType>("-sample", ExtraType.Sample)
|
||||
};
|
||||
|
||||
public List<ItemImageInfo> ImageInfos { get; set; }
|
||||
|
||||
@@ -167,7 +176,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
// Local trailer, special feature, theme video, etc.
|
||||
// An item that belongs to another item but is not part of the Parent-Child tree
|
||||
return !IsFolder && Parent == null;
|
||||
return !IsFolder && Parent == null && LocationType == LocationType.FileSystem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,11 +561,24 @@ namespace MediaBrowser.Controller.Entities
|
||||
.Where(i => string.Equals(i.Name, TrailerFolderName, StringComparison.OrdinalIgnoreCase))
|
||||
.SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
|
||||
.ToList();
|
||||
|
||||
// Support plex/xbmc convention
|
||||
|
||||
var extraTypes = new List<ExtraType> { ExtraType.Trailer };
|
||||
var suffixes = ExtraSuffixes.Where(i => extraTypes.Contains(i.Value))
|
||||
.Select(i => i.Key)
|
||||
.ToList();
|
||||
|
||||
files.AddRange(fileSystemChildren.OfType<FileInfo>()
|
||||
.Where(i => FileSystem.GetFileNameWithoutExtension(i).EndsWith(XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) && !string.Equals(Path, i.FullName, StringComparison.OrdinalIgnoreCase))
|
||||
);
|
||||
.Where(i =>
|
||||
{
|
||||
var nameEithoutExtension = FileSystem.GetFileNameWithoutExtension(i);
|
||||
|
||||
if (!suffixes.Any(s => nameEithoutExtension.EndsWith(s, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !string.Equals(Path, i.FullName, StringComparison.OrdinalIgnoreCase);
|
||||
}));
|
||||
|
||||
return LibraryManager.ResolvePaths<Trailer>(files, directoryService, null).Select(video =>
|
||||
{
|
||||
@@ -568,12 +590,79 @@ namespace MediaBrowser.Controller.Entities
|
||||
video = dbItem;
|
||||
}
|
||||
|
||||
if (video != null)
|
||||
{
|
||||
video.ExtraType = ExtraType.Trailer;
|
||||
}
|
||||
|
||||
return video;
|
||||
|
||||
// Sort them so that the list can be easily compared for changes
|
||||
}).OrderBy(i => i.Path).ToList();
|
||||
}
|
||||
|
||||
protected IEnumerable<Video> LoadSpecialFeatures(List<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService)
|
||||
{
|
||||
var files = fileSystemChildren.OfType<DirectoryInfo>()
|
||||
.Where(i => string.Equals(i.Name, "extras", StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, "specials", StringComparison.OrdinalIgnoreCase))
|
||||
.SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
|
||||
.ToList();
|
||||
|
||||
var extraTypes = new List<ExtraType> { ExtraType.BehindTheScenes, ExtraType.DeletedScene, ExtraType.Interview, ExtraType.Sample, ExtraType.Scene, ExtraType.Clip };
|
||||
var suffixes = ExtraSuffixes.Where(i => extraTypes.Contains(i.Value))
|
||||
.Select(i => i.Key)
|
||||
.ToList();
|
||||
|
||||
files.AddRange(fileSystemChildren.OfType<FileInfo>()
|
||||
.Where(i =>
|
||||
{
|
||||
var nameEithoutExtension = FileSystem.GetFileNameWithoutExtension(i);
|
||||
|
||||
if (!suffixes.Any(s => nameEithoutExtension.EndsWith(s, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !string.Equals(Path, i.FullName, StringComparison.OrdinalIgnoreCase);
|
||||
}));
|
||||
|
||||
return LibraryManager.ResolvePaths<Video>(files, directoryService, null).Select(video =>
|
||||
{
|
||||
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
||||
var dbItem = LibraryManager.GetItemById(video.Id) as Video;
|
||||
|
||||
if (dbItem != null)
|
||||
{
|
||||
video = dbItem;
|
||||
}
|
||||
|
||||
if (video != null)
|
||||
{
|
||||
SetExtraTypeFromFilename(video);
|
||||
}
|
||||
|
||||
return video;
|
||||
|
||||
// Sort them so that the list can be easily compared for changes
|
||||
}).OrderBy(i => i.Path).ToList();
|
||||
}
|
||||
|
||||
private void SetExtraTypeFromFilename(Video item)
|
||||
{
|
||||
var name = System.IO.Path.GetFileNameWithoutExtension(item.Path) ?? string.Empty;
|
||||
|
||||
foreach (var suffix in ExtraSuffixes)
|
||||
{
|
||||
if (name.EndsWith(suffix.Key, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
item.ExtraType = suffix.Value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
item.ExtraType = ExtraType.Clip;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the theme songs.
|
||||
/// </summary>
|
||||
@@ -600,6 +689,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
audio = dbItem;
|
||||
}
|
||||
|
||||
if (audio != null)
|
||||
{
|
||||
audio.ExtraType = ExtraType.ThemeSong;
|
||||
}
|
||||
|
||||
return audio;
|
||||
|
||||
// Sort them so that the list can be easily compared for changes
|
||||
@@ -626,6 +720,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
item = dbItem;
|
||||
}
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
item.ExtraType = ExtraType.ThemeVideo;
|
||||
}
|
||||
|
||||
return item;
|
||||
|
||||
// Sort them so that the list can be easily compared for changes
|
||||
|
||||
@@ -25,16 +25,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
var current = item.RemoteTrailers.FirstOrDefault(i => string.Equals(i.Url, url, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (current != null)
|
||||
{
|
||||
current.IsDirectLink = isDirectLink;
|
||||
}
|
||||
else
|
||||
if (current == null)
|
||||
{
|
||||
item.RemoteTrailers.Add(new MediaUrl
|
||||
{
|
||||
Url = url,
|
||||
IsDirectLink = isDirectLink
|
||||
Url = url
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||
return hasChanges;
|
||||
}
|
||||
|
||||
private async Task<bool> RefreshSpecialFeatures(MetadataRefreshOptions options, IEnumerable<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
|
||||
private async Task<bool> RefreshSpecialFeatures(MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
|
||||
{
|
||||
var newItems = LoadSpecialFeatures(fileSystemChildren, options.DirectoryService).ToList();
|
||||
var newItemIds = newItems.Select(i => i.Id).ToList();
|
||||
@@ -141,32 +141,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||
return itemsChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the special features.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{Video}.</returns>
|
||||
private IEnumerable<Video> LoadSpecialFeatures(IEnumerable<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService)
|
||||
{
|
||||
var files = fileSystemChildren.OfType<DirectoryInfo>()
|
||||
.Where(i => string.Equals(i.Name, "extras", StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, "specials", StringComparison.OrdinalIgnoreCase))
|
||||
.SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly));
|
||||
|
||||
return LibraryManager.ResolvePaths<Video>(files, directoryService, null).Select(video =>
|
||||
{
|
||||
// Try to retrieve it from the db. If we don't find it, use the resolved version
|
||||
var dbItem = LibraryManager.GetItemById(video.Id) as Video;
|
||||
|
||||
if (dbItem != null)
|
||||
{
|
||||
video = dbItem;
|
||||
}
|
||||
|
||||
return video;
|
||||
|
||||
// Sort them so that the list can be easily compared for changes
|
||||
}).OrderBy(i => i.Path).ToList();
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserConfiguration config)
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
public string Container { get; set; }
|
||||
public int? TotalBitrate { get; set; }
|
||||
public string ShortOverview { get; set; }
|
||||
public ExtraType ExtraType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timestamp.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MediaBrowser.Controller.Library
|
||||
{
|
||||
@@ -14,12 +15,18 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>IEnumerable{System.String}.</returns>
|
||||
IEnumerable<IntroInfo> GetIntros(BaseItem item, User user);
|
||||
Task<IEnumerable<IntroInfo>> GetIntros(BaseItem item, User user);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all intro files.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerable{System.String}.</returns>
|
||||
IEnumerable<string> GetAllIntroFiles();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace MediaBrowser.Controller.Library
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>IEnumerable{System.String}.</returns>
|
||||
IEnumerable<Video> GetIntros(BaseItem item, User user);
|
||||
Task<IEnumerable<Video>> GetIntros(BaseItem item, User user);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all intro files.
|
||||
|
||||
@@ -234,6 +234,7 @@
|
||||
<Compile Include="Providers\DirectoryService.cs" />
|
||||
<Compile Include="Providers\ICustomMetadataProvider.cs" />
|
||||
<Compile Include="Providers\IExternalId.cs" />
|
||||
<Compile Include="Providers\IExtrasProvider.cs" />
|
||||
<Compile Include="Providers\IForcedProvider.cs" />
|
||||
<Compile Include="Providers\IHasChangeMonitor.cs" />
|
||||
<Compile Include="Entities\IHasMetadata.cs" />
|
||||
|
||||
39
MediaBrowser.Controller/Providers/IExtrasProvider.cs
Normal file
39
MediaBrowser.Controller/Providers/IExtrasProvider.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Providers
|
||||
{
|
||||
public interface IExtrasProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Supportses the specified item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
||||
bool Supports(IHasMetadata item);
|
||||
}
|
||||
|
||||
public enum ExtraSource
|
||||
{
|
||||
Local = 1,
|
||||
Metadata = 2,
|
||||
Remote = 3
|
||||
}
|
||||
|
||||
public class ExtraInfo
|
||||
{
|
||||
public string Path { get; set; }
|
||||
|
||||
public LocationType LocationType { get; set; }
|
||||
|
||||
public bool IsDownloadable { get; set; }
|
||||
|
||||
public ExtraType ExtraType { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Channels;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -236,4 +237,9 @@ namespace MediaBrowser.Controller.Providers
|
||||
|
||||
public int SeasonIndex { get; set; }
|
||||
}
|
||||
|
||||
public class ChannelItemLookupInfo : ItemLookupInfo
|
||||
{
|
||||
public ChannelMediaContentType ContentType { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,9 +158,10 @@ namespace MediaBrowser.Controller.Resolvers
|
||||
// Normalize
|
||||
// Remove whitespace
|
||||
filename = filename.Replace("-", string.Empty);
|
||||
filename = filename.Replace(".", string.Empty);
|
||||
filename = Regex.Replace(filename, @"\s+", "");
|
||||
|
||||
var prefixes = new[] { "disc", "cd", "disk" };
|
||||
var prefixes = new[] { "disc", "cd", "disk", "vol", "volume" };
|
||||
|
||||
foreach (var prefix in prefixes)
|
||||
{
|
||||
@@ -210,7 +211,7 @@ namespace MediaBrowser.Controller.Resolvers
|
||||
{
|
||||
if (includeCreationTime)
|
||||
{
|
||||
item.DateCreated = fileSystem.GetCreationTimeUtc(childData);
|
||||
item.DateCreated = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
item.DateModified = fileSystem.GetLastWriteTimeUtc(childData);
|
||||
@@ -223,7 +224,7 @@ namespace MediaBrowser.Controller.Resolvers
|
||||
{
|
||||
if (includeCreationTime)
|
||||
{
|
||||
item.DateCreated = fileSystem.GetCreationTimeUtc(fileData);
|
||||
item.DateCreated = DateTime.UtcNow;
|
||||
}
|
||||
item.DateModified = fileSystem.GetLastWriteTimeUtc(fileData);
|
||||
}
|
||||
@@ -233,7 +234,7 @@ namespace MediaBrowser.Controller.Resolvers
|
||||
{
|
||||
if (includeCreationTime)
|
||||
{
|
||||
item.DateCreated = fileSystem.GetCreationTimeUtc(args.FileInfo);
|
||||
item.DateCreated = DateTime.UtcNow;
|
||||
}
|
||||
item.DateModified = fileSystem.GetLastWriteTimeUtc(args.FileInfo);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user